project-launcher changes

This commit is contained in:
m3tm3re
2026-01-06 05:54:39 +01:00
parent 5f8b5dbcdc
commit 6e6e819150
4 changed files with 112 additions and 54 deletions

View File

@@ -1,11 +1,11 @@
{
lib,
writeShellScriptBin,
rofi,
libnotify,
coreutils,
gnugrep,
gnused,
jq,
}:
writeShellScriptBin "rofi-project-opener" ''
#!/usr/bin/env bash
@@ -24,9 +24,12 @@ writeShellScriptBin "rofi-project-opener" ''
BASENAME="${coreutils}/bin/basename"
GREP="${gnugrep}/bin/grep"
SED="${gnused}/bin/sed"
JQ="${jq}/bin/jq"
# Configuration from config file or environment variables
CONFIG_FILE="''${XDG_CONFIG_HOME:-$HOME/.config}/rofi-project-opener/config"
# Configuration files
CONFIG_DIR="''${XDG_CONFIG_HOME:-$HOME/.config}/rofi-project-opener"
CONFIG_FILE="$CONFIG_DIR/config"
PROJECTS_JSON="$CONFIG_DIR/projects.json"
if [[ -f "$CONFIG_FILE" ]]; then
# shellcheck disable=SC1090
@@ -34,12 +37,19 @@ writeShellScriptBin "rofi-project-opener" ''
fi
# Fallback to environment variables or defaults
PROJECT_DIRS="''${PROJECT_DIRS:-$HOME}"
TERMINAL="''${TERMINAL:-kitty}"
TERMINAL_CMD="''${TERMINAL_CMD:-}"
ROFI_PROMPT="''${ROFI_PROMPT:-Select project}"
ROFI_ARGS="''${ROFI_ARGS:--dmenu -i}"
# Check for projects.json
if [[ ! -f "$PROJECTS_JSON" ]]; then
echo "[rofi-project-opener] Error: No projects.json found at $PROJECTS_JSON" >&2
"$NOTIFY" -u critical -a "rofi-project-opener" "No projects.json configuration found"
exit 1
fi
PROJECTS_JSON_DATA="$(cat "$PROJECTS_JSON")"
# Temporary file for project list
PROJECTS_LIST="''${XDG_RUNTIME_DIR:-/tmp}/rofi-project-opener.$$"
@@ -59,26 +69,33 @@ writeShellScriptBin "rofi-project-opener" ''
"$NOTIFY" -u critical -a "rofi-project-opener" "$message"
}
# Build list of projects
# Build list of projects from JSON config
# Format: display_name|full_path|args
build_project_list() {
> "$PROJECTS_LIST"
# Split PROJECT_DIRS by colon and iterate
IFS=':' read -ra DIR_ARRAY <<< "$PROJECT_DIRS"
for base_dir in "''${DIR_ARRAY[@]}"; do
# Parse JSON and iterate over each base directory entry
local keys
keys=$(echo "$PROJECTS_JSON_DATA" | "$JQ" -r 'keys[]')
for key in $keys; do
local base_path base_args
base_path=$(echo "$PROJECTS_JSON_DATA" | "$JQ" -r --arg k "$key" '.[$k].path')
base_args=$(echo "$PROJECTS_JSON_DATA" | "$JQ" -r --arg k "$key" '.[$k].args // ""')
# Expand ~ to $HOME
base_dir="''${base_dir/#\~/$HOME}"
base_path="''${base_path/#\~/$HOME}"
# Expand $HOME variable (allows both ~ and $HOME in config)
base_dir="$(eval echo "$base_dir")"
base_path="$(eval echo "$base_path")"
# Skip if directory doesn't exist
if [[ ! -d "$base_dir" ]]; then
echo "[rofi-project-opener] Warning: Directory does not exist: $base_dir" >&2
if [[ ! -d "$base_path" ]]; then
echo "[rofi-project-opener] Warning: Directory does not exist: $base_path" >&2
continue
fi
# Find 1st level subdirectories (non-hidden)
for project in "$base_dir"/*/; do
for project in "$base_path"/*/; do
if [[ -d "$project" ]]; then
# Get directory name without trailing slash
project_path="''${project%/}"
@@ -89,8 +106,8 @@ writeShellScriptBin "rofi-project-opener" ''
continue
fi
base_display="$("$BASENAME" "$base_dir")"
echo "$base_display/$project_name|$project_path" >> "$PROJECTS_LIST"
# Use key as display prefix (e.g., "dev/myproject")
echo "$key/$project_name|$project_path|$base_args" >> "$PROJECTS_LIST"
fi
done
done
@@ -101,7 +118,7 @@ writeShellScriptBin "rofi-project-opener" ''
# Build project list
if ! build_project_list; then
show_error "No projects found in PROJECT_DIRS: $PROJECT_DIRS"
show_error "No projects found in configured directories"
exit 1
fi
@@ -117,8 +134,10 @@ writeShellScriptBin "rofi-project-opener" ''
exit 0
fi
# Get the full path from selection
project_path=$("$GREP" "^$selection|" "$PROJECTS_LIST" | "$CUT" -d '|' -f2)
# Get the full path and args from selection
selected_line=$("$GREP" "^$selection|" "$PROJECTS_LIST")
project_path=$(echo "$selected_line" | "$CUT" -d '|' -f2)
project_args=$(echo "$selected_line" | "$CUT" -d '|' -f3)
# Exit if path not found (shouldn't happen)
if [[ -z "$project_path" ]]; then
@@ -133,33 +152,30 @@ writeShellScriptBin "rofi-project-opener" ''
fi
# Build terminal command
# Placeholders: %s = project path, %a = project args
if [[ -n "$TERMINAL_CMD" ]]; then
# Check if %s placeholder is present
if [[ "$TERMINAL_CMD" == *"%s"* ]]; then
# Replace %s with project path and use as-is
final_cmd="''${TERMINAL_CMD//%s/$project_path}"
# shellcheck disable=SC2086
exec "$TERMINAL" $final_cmd
else
# Treat as command to run: wrap in shell with cd (--hold keeps terminal open)
# Source /etc/profile (base PATH) and HM session vars (sessionPath) for NixOS
exec "$TERMINAL" --hold -e bash --login -c "
unset __HM_SESS_VARS_SOURCED
for f in ~/.nix-profile/etc/profile.d/hm-session-vars.sh /etc/profiles/per-user/\$USER/etc/profile.d/hm-session-vars.sh; do
[ -f \"\$f\" ] && . \"\$f\"
done
cd '$project_path' && exec $TERMINAL_CMD
"
fi
else
# Default: open terminal, cd to project, run opencode
# Substitute placeholders
final_cmd="$TERMINAL_CMD"
final_cmd="''${final_cmd//%s/$project_path}"
final_cmd="''${final_cmd//%a/$project_args}"
# Source /etc/profile (base PATH) and HM session vars (sessionPath) for NixOS
exec "$TERMINAL" --hold -e bash --login -c "
unset __HM_SESS_VARS_SOURCED
for f in ~/.nix-profile/etc/profile.d/hm-session-vars.sh /etc/profiles/per-user/\$USER/etc/profile.d/hm-session-vars.sh; do
[ -f \"\$f\" ] && . \"\$f\"
done
cd '$project_path' && opencode
cd '$project_path' && exec $final_cmd
"
else
# Default: open terminal, cd to project, run opencode with args
# Source /etc/profile (base PATH) and HM session vars (sessionPath) for NixOS
exec "$TERMINAL" --hold -e bash --login -c "
unset __HM_SESS_VARS_SOURCED
for f in ~/.nix-profile/etc/profile.d/hm-session-vars.sh /etc/profiles/per-user/\$USER/etc/profile.d/hm-session-vars.sh; do
[ -f \"\$f\" ] && . \"\$f\"
done
cd '$project_path' && opencode $project_args
"
fi
''