├── .gitattributes
├── .gitignore
├── README.md
├── build.gradle
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
├── settings.gradle
└── src
└── main
├── java
└── QuickSwitchAction.java
└── resources
└── META-INF
└── plugin.xml
/.gitattributes:
--------------------------------------------------------------------------------
1 | #
2 | # https://help.github.com/articles/dealing-with-line-endings/
3 | #
4 | # These are explicitly windows files and should use crlf
5 | *.bat text eol=crlf
6 |
7 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea/
2 | .gradle/
3 |
4 | *.iws
5 | *.iml
6 |
7 | out/
8 | build/
9 |
10 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # angular-cli-quick-switch-plugin
2 |
3 | IntelliJ Plugin for switching amongst Angular CLI component files efficiently (e.g. ts -> html -> css) by just using one shortcut (**Alt+S**).
4 |
5 | For example let's say we have a structure like this
6 |
7 | foo/
8 | bar.info
9 | foo.component.css
10 | foo.component.html
11 | **foo.component.ts**
12 | foo.md
13 |
14 | By pressing the assigned shortcut repeatedly, the IDE will cycle amongst the files as follows:
15 |
16 | foo.component.ts -> foo.component.html -> foo.component.css -> foo.component.ts -> ...
17 |
18 |
19 | Whilst cycling, unknown filenames (like bar.info) and extensions (like foo.md) will be skipped on purpose.
20 |
21 | Explicitly whitelisted extensions are:
22 | - js, ts
23 | - html, php, haml, jade, pug, slim
24 | - css, sass, scss, less, styl
25 |
26 | Note:
27 | For switching between your code and test/spec files, you can simply use the built in default shortcut from IntelliJ (**Ctrl+Shift+T**)
28 |
29 |
30 |
31 | Further information:
32 |
33 | If the default shortcut **Alt + S** does not fit your needs, you can of course easily adjust it in the keymap settings by replacing it for **QuickSwitch**.
34 |
35 | Due to the nature of this plugin, it will of course also **work with other projects**, that have not been generated by Angular CLI - or are
36 | not even Angular projects at all - as long as your project structure follows similar patterns.
--------------------------------------------------------------------------------
/build.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * This file was generated by the Gradle 'init' task.
3 | *
4 | * This is a general purpose Gradle build.
5 | * Learn how to create Gradle builds at https://guides.gradle.org/creating-new-gradle-builds
6 | */
7 |
8 | plugins {
9 | id 'java'
10 | id 'idea'
11 | id 'org.jetbrains.intellij' version '0.4.21'
12 | }
13 |
14 | group 'patrick.kelleter'
15 | version '1.3.1'
16 |
17 | apply plugin: 'java'
18 |
19 | java {
20 | sourceCompatibility = JavaVersion.VERSION_11
21 | }
22 |
23 | repositories {
24 | mavenCentral()
25 | }
26 |
27 | dependencies {
28 | testCompileOnly 'junit:junit:4.12'
29 | }
30 |
31 | intellij {
32 | updateSinceUntilBuild false
33 | }
34 | patchPluginXml {
35 | changeNotes """
36 | - Added support for php, haml, jade, pug, slim, less, styl files.
- Updated docs
"""
37 | }
38 |
39 | task wrapper(type: Wrapper) {
40 | gradleVersion = '6.5'
41 | }
42 |
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/pkelleter/angular-cli-quick-switch-plugin/ecf71027d608fd52b4121b44509f844537636d31/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Wed Jun 03 13:15:19 CEST 2020
2 | distributionUrl=https\://services.gradle.org/distributions/gradle-6.5-all.zip
3 | distributionBase=GRADLE_USER_HOME
4 | distributionPath=wrapper/dists
5 | zipStorePath=wrapper/dists
6 | zipStoreBase=GRADLE_USER_HOME
7 |
--------------------------------------------------------------------------------
/gradlew:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | ##############################################################################
4 | ##
5 | ## Gradle start up script for UN*X
6 | ##
7 | ##############################################################################
8 |
9 | # Attempt to set APP_HOME
10 | # Resolve links: $0 may be a link
11 | PRG="$0"
12 | # Need this for relative symlinks.
13 | while [ -h "$PRG" ] ; do
14 | ls=`ls -ld "$PRG"`
15 | link=`expr "$ls" : '.*-> \(.*\)$'`
16 | if expr "$link" : '/.*' > /dev/null; then
17 | PRG="$link"
18 | else
19 | PRG=`dirname "$PRG"`"/$link"
20 | fi
21 | done
22 | SAVED="`pwd`"
23 | cd "`dirname \"$PRG\"`/" >/dev/null
24 | APP_HOME="`pwd -P`"
25 | cd "$SAVED" >/dev/null
26 |
27 | APP_NAME="Gradle"
28 | APP_BASE_NAME=`basename "$0"`
29 |
30 | # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
31 | DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
32 |
33 | # Use the maximum available, or set MAX_FD != -1 to use that value.
34 | MAX_FD="maximum"
35 |
36 | warn () {
37 | echo "$*"
38 | }
39 |
40 | die () {
41 | echo
42 | echo "$*"
43 | echo
44 | exit 1
45 | }
46 |
47 | # OS specific support (must be 'true' or 'false').
48 | cygwin=false
49 | msys=false
50 | darwin=false
51 | nonstop=false
52 | case "`uname`" in
53 | CYGWIN* )
54 | cygwin=true
55 | ;;
56 | Darwin* )
57 | darwin=true
58 | ;;
59 | MINGW* )
60 | msys=true
61 | ;;
62 | NONSTOP* )
63 | nonstop=true
64 | ;;
65 | esac
66 |
67 | CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
68 |
69 |
70 | # Determine the Java command to use to start the JVM.
71 | if [ -n "$JAVA_HOME" ] ; then
72 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
73 | # IBM's JDK on AIX uses strange locations for the executables
74 | JAVACMD="$JAVA_HOME/jre/sh/java"
75 | else
76 | JAVACMD="$JAVA_HOME/bin/java"
77 | fi
78 | if [ ! -x "$JAVACMD" ] ; then
79 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
80 |
81 | Please set the JAVA_HOME variable in your environment to match the
82 | location of your Java installation."
83 | fi
84 | else
85 | JAVACMD="java"
86 | which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
87 |
88 | Please set the JAVA_HOME variable in your environment to match the
89 | location of your Java installation."
90 | fi
91 |
92 | # Increase the maximum file descriptors if we can.
93 | if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
94 | MAX_FD_LIMIT=`ulimit -H -n`
95 | if [ $? -eq 0 ] ; then
96 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
97 | MAX_FD="$MAX_FD_LIMIT"
98 | fi
99 | ulimit -n $MAX_FD
100 | if [ $? -ne 0 ] ; then
101 | warn "Could not set maximum file descriptor limit: $MAX_FD"
102 | fi
103 | else
104 | warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
105 | fi
106 | fi
107 |
108 | # For Darwin, add options to specify how the application appears in the dock
109 | if $darwin; then
110 | GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
111 | fi
112 |
113 | # For Cygwin or MSYS, switch paths to Windows format before running java
114 | if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
115 | APP_HOME=`cygpath --path --mixed "$APP_HOME"`
116 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
117 |
118 | JAVACMD=`cygpath --unix "$JAVACMD"`
119 |
120 | # We build the pattern for arguments to be converted via cygpath
121 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
122 | SEP=""
123 | for dir in $ROOTDIRSRAW ; do
124 | ROOTDIRS="$ROOTDIRS$SEP$dir"
125 | SEP="|"
126 | done
127 | OURCYGPATTERN="(^($ROOTDIRS))"
128 | # Add a user-defined pattern to the cygpath arguments
129 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then
130 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
131 | fi
132 | # Now convert the arguments - kludge to limit ourselves to /bin/sh
133 | i=0
134 | for arg in "$@" ; do
135 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
136 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
137 |
138 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
139 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
140 | else
141 | eval `echo args$i`="\"$arg\""
142 | fi
143 | i=`expr $i + 1`
144 | done
145 | case $i in
146 | 0) set -- ;;
147 | 1) set -- "$args0" ;;
148 | 2) set -- "$args0" "$args1" ;;
149 | 3) set -- "$args0" "$args1" "$args2" ;;
150 | 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
151 | 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
152 | 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
153 | 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
154 | 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
155 | 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
156 | esac
157 | fi
158 |
159 | # Escape application args
160 | save () {
161 | for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
162 | echo " "
163 | }
164 | APP_ARGS=`save "$@"`
165 |
166 | # Collect all arguments for the java command, following the shell quoting and substitution rules
167 | eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
168 |
169 | exec "$JAVACMD" "$@"
170 |
--------------------------------------------------------------------------------
/gradlew.bat:
--------------------------------------------------------------------------------
1 | @if "%DEBUG%" == "" @echo off
2 | @rem ##########################################################################
3 | @rem
4 | @rem Gradle startup script for Windows
5 | @rem
6 | @rem ##########################################################################
7 |
8 | @rem Set local scope for the variables with windows NT shell
9 | if "%OS%"=="Windows_NT" setlocal
10 |
11 | set DIRNAME=%~dp0
12 | if "%DIRNAME%" == "" set DIRNAME=.
13 | set APP_BASE_NAME=%~n0
14 | set APP_HOME=%DIRNAME%
15 |
16 | @rem Resolve any "." and ".." in APP_HOME to make it shorter.
17 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
18 |
19 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
20 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
21 |
22 | @rem Find java.exe
23 | if defined JAVA_HOME goto findJavaFromJavaHome
24 |
25 | set JAVA_EXE=java.exe
26 | %JAVA_EXE% -version >NUL 2>&1
27 | if "%ERRORLEVEL%" == "0" goto init
28 |
29 | echo.
30 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
31 | echo.
32 | echo Please set the JAVA_HOME variable in your environment to match the
33 | echo location of your Java installation.
34 |
35 | goto fail
36 |
37 | :findJavaFromJavaHome
38 | set JAVA_HOME=%JAVA_HOME:"=%
39 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe
40 |
41 | if exist "%JAVA_EXE%" goto init
42 |
43 | echo.
44 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
45 | echo.
46 | echo Please set the JAVA_HOME variable in your environment to match the
47 | echo location of your Java installation.
48 |
49 | goto fail
50 |
51 | :init
52 | @rem Get command-line arguments, handling Windows variants
53 |
54 | if not "%OS%" == "Windows_NT" goto win9xME_args
55 |
56 | :win9xME_args
57 | @rem Slurp the command line arguments.
58 | set CMD_LINE_ARGS=
59 | set _SKIP=2
60 |
61 | :win9xME_args_slurp
62 | if "x%~1" == "x" goto execute
63 |
64 | set CMD_LINE_ARGS=%*
65 |
66 | :execute
67 | @rem Setup the command line
68 |
69 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
70 |
71 |
72 | @rem Execute Gradle
73 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
74 |
75 | :end
76 | @rem End local scope for the variables with windows NT shell
77 | if "%ERRORLEVEL%"=="0" goto mainEnd
78 |
79 | :fail
80 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
81 | rem the _cmd.exe /c_ return code!
82 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
83 | exit /b 1
84 |
85 | :mainEnd
86 | if "%OS%"=="Windows_NT" endlocal
87 |
88 | :omega
89 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | /*
2 | * This file was generated by the Gradle 'init' task.
3 | *
4 | * The settings file is used to specify which projects to include in your build.
5 | *
6 | * Detailed information about configuring a multi-project build in Gradle can be found
7 | * in the user manual at https://docs.gradle.org/6.5/userguide/multi_project_builds.html
8 | */
9 |
10 | rootProject.name = 'angular-cli-quick-switch-plugin'
11 |
--------------------------------------------------------------------------------
/src/main/java/QuickSwitchAction.java:
--------------------------------------------------------------------------------
1 | import com.intellij.openapi.actionSystem.AnAction;
2 | import com.intellij.openapi.actionSystem.AnActionEvent;
3 | import com.intellij.openapi.fileEditor.FileEditorManager;
4 | import com.intellij.openapi.fileEditor.OpenFileDescriptor;
5 | import com.intellij.openapi.project.Project;
6 | import com.intellij.openapi.vfs.LocalFileSystem;
7 | import com.intellij.openapi.vfs.VirtualFile;
8 |
9 | import java.util.Arrays;
10 | import java.util.List;
11 |
12 | public class QuickSwitchAction extends AnAction {
13 |
14 | private AnActionEvent latestEvent;
15 |
16 | private List extensions = Arrays.asList(
17 | "ts", "js",
18 | "html", "php", "haml", "jade", "pug", "slim",
19 | "css", "sass", "scss", "less", "styl"
20 | );
21 |
22 | public QuickSwitchAction() {
23 | super("QuickSwitch");
24 | }
25 |
26 | @Override
27 | public void actionPerformed(AnActionEvent event) {
28 | this.latestEvent = event;
29 |
30 | VirtualFile currentFile = (VirtualFile) event.getDataContext().getData("virtualFile");
31 | if (currentFile == null) return;
32 |
33 | String currentFilePath = currentFile.getCanonicalPath();
34 | if (currentFilePath == null) return;
35 |
36 | String basePath = this.removeFilePathExtension(currentFilePath);
37 | String extension = this.getFilePathExtension(currentFilePath);
38 | if (basePath == null || extension == null) return;
39 |
40 | String newPath = this.cycleExtension(basePath, extension);
41 | this.switchFile(currentFilePath, newPath);
42 | }
43 |
44 | private String getFilePathExtension(String filePath) {
45 | int extensionPosition = filePath.lastIndexOf(".");
46 | if (extensionPosition == -1) return null;
47 | return filePath.substring(extensionPosition + 1);
48 | }
49 |
50 | private String removeFilePathExtension(String filePath) {
51 | int extensionPosition = filePath.lastIndexOf(".");
52 | if (extensionPosition == -1) return filePath;
53 | return filePath.substring(0, extensionPosition);
54 | }
55 |
56 | private String cycleExtension(String basePath, String currentExtension) {
57 | String currentPath = basePath + "." + currentExtension;
58 | int currentIndex = this.extensions.indexOf(currentExtension);
59 | if (currentIndex == -1) return currentPath;
60 | for (int i = 0; i < this.extensions.size(); i++) {
61 | int newIndex = ((currentIndex + 1 + i) % this.extensions.size());
62 | String newExtension = this.extensions.get(newIndex);
63 | String newPath = basePath + "." + newExtension;
64 | VirtualFile newFile = this.getFileByPath(newPath);
65 | if (newFile != null && newFile.exists()) return newPath;
66 | }
67 | return currentPath;
68 | }
69 |
70 | private void switchFile(String currentFilePath, String newFilePath) {
71 | Project project = this.latestEvent.getProject();
72 | if (project == null) return;
73 | VirtualFile currentFile = this.getFileByPath(currentFilePath);
74 | VirtualFile newFile = this.getFileByPath(newFilePath);
75 | if (!currentFile.exists() || !newFile.exists()) return;
76 | FileEditorManager.getInstance(project).closeFile(currentFile);
77 | new OpenFileDescriptor(project, newFile).navigate(true);
78 | }
79 |
80 | private VirtualFile getFileByPath(String path) {
81 | return LocalFileSystem.getInstance().findFileByPath(path);
82 | }
83 |
84 | }
85 |
--------------------------------------------------------------------------------
/src/main/resources/META-INF/plugin.xml:
--------------------------------------------------------------------------------
1 |
2 | patrick.kelleter.angular-cli-quick-switch
3 | Angular CLI QuickSwitch
4 | Patrick Kelleter
5 |
6 |
9 |
10 | - Updated docs
12 | ]]>
13 |
14 |
15 |
16 |
17 | com.intellij.modules.lang
18 |
19 |
20 |
21 |
22 |
23 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------