Skip to content

[bin] jetbrains-cli-helper: Refactor JetBrains CLI Launchers into Centralized Helper #34

@0xdevalias

Description

@0xdevalias

Currently, there are multiple overlapping JetBrains launcher scripts in ~/.dotfiles/bin (e.g., goland, intellij, idea, mine, rubymine, webstorm). Many are near-duplicates or lightweight shims. The new bin/jetbrains-cli-helper aims to consolidate this logic into a single entrypoint, reducing duplication and making it easier to manage PATH differences (Toolbox vs Homebrew, etc).

The goal is to refactor or replace the scattered scripts with lightweight wrappers or aliases that call back into this centralized helper.

Current Local WIP

bin/jetbrains-cli-helper:

#!/usr/bin/env zsh

# TODO: Refactor the following scripts to be lightweight shims that call back into this tool (or remove them and replace with aliases?)
#   ~/.dotfiles/bin/goland
#   ~/.dotfiles/bin/intellij
#   ~/.dotfiles/bin/idea     # Lightweight shim for intellij
#   ~/.dotfiles/bin/mine     # Almost duplicate of rubymine
#   ~/.dotfiles/bin/rubymine # Almost duplicate of mine
#   ~/.dotfiles/bin/webstorm
#   etc?

# Array of prioritized paths for JetBrains launcher scripts
POSSIBLE_PATHS=(
  "$HOME/Library/Application Support/JetBrains/Toolbox/scripts"  # JetBrains Toolbox default
  "$(brew --prefix)/bin"                                         # Homebrew bin directory
)

# Function to display usage/help
show_help() {
  cat <<EOF
Usage: jetbrains-cli-helper <tool-name> [args...]

Launch a JetBrains IDE from the command line.

Arguments:
  <tool-name>     The name of the JetBrains tool to launch (e.g., webstorm, intellij, goland).
  [args...]       Additional arguments to pass to the launcher.

Examples:
  jetbrains-cli-helper webstorm              # Launch WebStorm in the current directory.
  jetbrains-cli-helper intellij myfile.java  # Open a specific file in IntelliJ IDEA.

Paths searched for the launcher:
  $(printf "%s\n  " "${POSSIBLE_PATHS[@]}")

EOF
}

# Function to display additional setup instructions if the binary isn't found
show_setup_instructions() {
  local tool_name="$1"
  cat <<EOF

Error: JetBrains launcher not found for '$tool_name'.

To configure the CLI launcher using JetBrains Toolbox:
  1. Open JetBrains Toolbox.
  2. Click the gear icon next to the desired IDE (e.g., WebStorm, IntelliJ).
  3. Select "Settings".
  4. Under "Generate shell scripts", specify a directory (e.g., "$HOME/Library/Application Support/JetBrains/Toolbox/scripts").
  5. Ensure the specified directory is included in your PATH and is one of the paths supported by this tool.

Alternatively, generate the CLI script directly from the IDE:
  1. Open the desired IDE (e.g., WebStorm, IntelliJ).
  2. Go to the main menu: Tools > Create Command-line Launcher.
  3. In the dialog that opens:
     - Specify the desired path (e.g., "$HOME/Library/Application Support/JetBrains/Toolbox/scripts").
     - Click OK to create the launcher script.
  4. Ensure the specified directory is included in your PATH and is one of the paths supported by this tool.

Paths searched:
  $(printf "%s\n  " "${POSSIBLE_PATHS[@]}")

EOF
}

# Function to find the specified JetBrains binary
find_jetbrains_bin() {
  local tool_name="$1"

  # Ensure the tool name is provided
  if [[ -z "$tool_name" ]]; then
    echo "Error: No tool name provided." >&2
    return 1
  fi

  for path in "${POSSIBLE_PATHS[@]}"; do
    local candidate="$path/$tool_name"

    # Resolve the canonical path of the candidate
    # local resolved_path=$(realpath "$candidate" 2>/dev/null || echo "")
    local resolved_path=$(realpath "$candidate")
    echo $(echo $PATH) 1>&2

    echo "A11A ${candidate} -> ${resolved_path} B11B" 1>&2

    # Skip if realpath failed (invalid file or path)
    if [[ -z "$resolved_path" ]]; then
      continue
    fi

    # Check if the resolved path is within a valid prefix
    local is_in_allowed_prefix=false
    for valid_prefix in "${POSSIBLE_PATHS[@]}"; do
      if [[ "$resolved_path" == "$valid_prefix/"* ]]; then
        is_in_allowed_prefix=true
        break
      fi
    done

    # If not in an allowed prefix, fail fast with an explicit error
    if [[ "$is_in_allowed_prefix" != true ]]; then
      echo "Error: Resolved path '$resolved_path' is outside the allowed directories." >&2
      return 1
    fi

    # If valid, return the resolved path
    echo "$resolved_path"
    return
  done

  # No valid binary found
  echo ""
}

# Main script logic
main() {
  # Show help if no arguments or -h/--help
  if [[ $# -eq 0 || "$1" == "-h" || "$1" == "--help" ]]; then
    show_help
    exit 0
  fi

  local tool_name="$1"
  shift

  # Find the binary for the specified tool
  local tool_bin=$(find_jetbrains_bin "$tool_name")
  local result_code=$?
  if [[ $result_code -ne 0 ]]; then
    # find_jetbrains_bin has already printed an error, so just exit
    return $result_code
  fi

  echo "AA${tool_bin}BB" 2>&1
  exit

  if [[ -z "$tool_bin" ]]; then
    show_setup_instructions "$tool_name"
    exit 1
  fi

  # Execute the launcher with the provided arguments
  exec "$tool_bin" "$PWD/$@" &
}

main "$@"

And I also had these diffs open but don't remember why / if they are still useful:

--- (clipboard)
+++ /Users/devalias/.dotfiles/bin/jetbrains-cli-helper (Selection)
@@ -11,34 +11,24 @@
     local candidate="$path/$tool_name"
 
     # Resolve the canonical path of the candidate
-    local resolved_path
-    resolved_path=$(realpath "$candidate" 2>/dev/null || echo "")
+    local resolved_path=$(realpath "$candidate" 2>/dev/null || echo "")
+
+    echo "A11A ${candidate} -> ${resolved_path} B11B" 1>&2
 
     # Skip if realpath failed (invalid file or path)
     if [[ -z "$resolved_path" ]]; then
       continue
     fi
 
-    # Check if the resolved path is within a valid prefix
-    local valid=false
+    # Check if the resolved path is valid and within the allowed prefix
     for valid_prefix in "${POSSIBLE_PATHS[@]}"; do
       if [[ "$resolved_path" == "$valid_prefix/"* ]]; then
-        valid=true
-        break
+        echo "$resolved_path"
+        return
       fi
     done
-
-    # If not valid, fail fast with an explicit error
-    if [[ "$valid" != true ]]; then
-      echo "Error: Resolved path '$resolved_path' is outside the allowed directories." >&2
-      return 1
-    fi
-
-    # If valid, return the resolved path
-    echo "$resolved_path"
-    return
   done
 
   # No valid binary found
   echo ""
-}
+}
--- (clipboard)
+++ /Users/devalias/.dotfiles/bin/jetbrains-cli-helper (Selection)
@@ -7,15 +7,18 @@
     return 1
   fi
 
-  for search_dir in "${POSSIBLE_PATHS[@]}"; do
-    local candidate="$search_dir/$tool_name"
-    local resolved_path=$(/usr/bin/realpath "$candidate" 2>/dev/null || echo "")
+  for path in "${POSSIBLE_PATHS[@]}"; do
+    local candidate="$path/$tool_name"
 
-    echo "Debug: Candidate path: '${candidate}' -> Resolved path: '${resolved_path}'" >&2
+    # Resolve the canonical path of the candidate
+    # local resolved_path=$(realpath "$candidate" 2>/dev/null || echo "")
+    local resolved_path=$(realpath "$candidate")
+    echo $(echo $PATH) 1>&2
+
+    echo "A11A ${candidate} -> ${resolved_path} B11B" 1>&2
 
     # Skip if realpath failed (invalid file or path)
     if [[ -z "$resolved_path" ]]; then
-      echo "Debug: realpath failed for '${candidate}'." >&2
       continue
     fi
 
@@ -28,9 +31,9 @@
       fi
     done
 
-    # Fail fast if not in an allowed prefix
+    # If not in an allowed prefix, fail fast with an explicit error
     if [[ "$is_in_allowed_prefix" != true ]]; then
-      echo "Error: Resolved path '${resolved_path}' is outside the allowed directories." >&2
+      echo "Error: Resolved path '$resolved_path' is outside the allowed directories." >&2
       return 1
     fi
 
@@ -41,4 +44,4 @@
 
   # No valid binary found
   echo ""
-}
+}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions