325 lines
12 KiB
Bash
325 lines
12 KiB
Bash
#!/bin/env bash
|
||
|
||
# folder names, change it depending on your language
|
||
documents="Documents"
|
||
music="Music"
|
||
pictures="Pictures"
|
||
videos="Videos"
|
||
downloads="Downloads"
|
||
|
||
declare -A PROJECT_ROOT_CACHE
|
||
export FIND_PROJECT_ROOT_DEBUG=0
|
||
|
||
find_project_root() {
|
||
local args=${@}
|
||
local cache_key="cache_$(echo -n $PWD | md5sum | cut -d' ' -f1)"
|
||
|
||
# args detection
|
||
for arg in ${args}; do
|
||
if [[ "${arg:0:2}" = "--" ]]; then
|
||
arg="${arg:2}"
|
||
|
||
case "${arg}" in
|
||
"help")
|
||
echo -e "Usage : find_project_root [OPTION(S)]\n"
|
||
echo "Find the folder that could be a project root."
|
||
echo "It is automatically called by the prompt generator but you can call it if you want to access or modify the cache.\n"
|
||
echo "The result is stocked in the env variable PROJECT_ROOT. The exit value is 0 when project root found or 1 if not."
|
||
echo "Options :"
|
||
echo " --print-cache print project root cache"
|
||
echo " --clear-cache clear project root cache ; WARNING : the cache is wiped automatically in new bash instances."
|
||
echo " --toggle-debug toggle debug mode"
|
||
echo " --help display this help"
|
||
return 0 ;;
|
||
|
||
"print-cache")
|
||
for key in ${!PROJECT_ROOT_CACHE[@]}; do
|
||
echo "[${key}]=${PROJECT_ROOT_CACHE[$key]}"
|
||
done ;;
|
||
|
||
"clear-cache")
|
||
PROJECT_ROOT_CACHE=() ;;
|
||
|
||
"toggle-debug")
|
||
FIND_PROJECT_ROOT_DEBUG=$((! FIND_PROJECT_ROOT_DEBUG)) ;;
|
||
|
||
*)
|
||
echo -e "Error : unrecognised parameter : --${arg}\n Try typing --help" ;;
|
||
esac
|
||
else
|
||
echo -e "Error : unrecognised parameter : ${arg}\n Try typing --help"
|
||
fi
|
||
done
|
||
|
||
# search cache for existing data
|
||
if [[ -n "${PROJECT_ROOT_CACHE[$cache_key]}" ]]; then
|
||
if [[ "${PROJECT_ROOT_CACHE[$cache_key]}" != "." ]]; then
|
||
PROJECT_ROOT="${PROJECT_ROOT_CACHE[$cache_key]}"
|
||
return 0
|
||
fi
|
||
|
||
PROJECT_ROOT=""
|
||
return 1
|
||
fi
|
||
|
||
# estimate probability of root dir
|
||
local depth=0
|
||
local current_dir="$PWD"
|
||
local current_max_score=0
|
||
local current_dir_score=0
|
||
local project_root="."
|
||
|
||
while (( depth < 10 )) && [[ "${current_dir}" != "/" ]]; do
|
||
current_dir_score=0
|
||
|
||
# 100% root
|
||
for path in README.md README.rst README LICENSE \
|
||
Dockerfile docker-compose.yml \
|
||
.git; do
|
||
if [[ -e "${current_dir}/${path}" ]]; then
|
||
(( FIND_PROJECT_ROOT_DEBUG )) && echo "${path}"
|
||
((current_dir_score += 100))
|
||
fi
|
||
done
|
||
|
||
# 90% root
|
||
for path in CMakeLists.txt \
|
||
Cargo.toml Cargo.lock \
|
||
go.mod go.sum \
|
||
pyproject.toml \
|
||
pom.xml \
|
||
package.json \
|
||
.csproj .sln; do
|
||
if [[ -e "${current_dir}/${path}" ]]; then
|
||
(( FIND_PROJECT_ROOT_DEBUG )) && echo "${path}"
|
||
((current_dir_score += 90))
|
||
fi
|
||
done
|
||
|
||
# 75% root
|
||
for path in Makefile \
|
||
requirements.txt \
|
||
build.gradle \
|
||
Gemfile \
|
||
tsconfig.json \
|
||
composer.json \
|
||
.gitignore; do
|
||
if [[ -e "${current_dir}/${path}" ]]; then
|
||
(( FIND_PROJECT_ROOT_DEBUG )) && echo "${path}"
|
||
((current_dir_score += 75))
|
||
fi
|
||
done
|
||
|
||
# 50% root
|
||
for path in webpack.config.js vite.config.js babel.config.js .babelrc rollup.config.js \
|
||
lib include config scripts bin src third_party 3rd_party vendor \
|
||
.env .env.local \
|
||
.dockerignore; do
|
||
if [[ -e "${current_dir}/${path}" ]]; then
|
||
(( FIND_PROJECT_ROOT_DEBUG )) && echo "${path}"
|
||
((current_dir_score += 50))
|
||
fi
|
||
done
|
||
|
||
# 25% root
|
||
for path in configure \
|
||
Gopkg.toml \
|
||
Pipfile Pipfile.lock setup.py tox.ini .python-version \
|
||
build.xml settings.gradle \
|
||
packages.config \
|
||
Directory.Build.props \
|
||
.htmlhintrc .stylelintrc \
|
||
Gemfile.lock \
|
||
composer.lock \
|
||
Rakefile; do
|
||
if [[ -e "${current_dir}/${path}" ]]; then
|
||
(( FIND_PROJECT_ROOT_DEBUG )) && echo "${path}"
|
||
((current_dir_score += 25))
|
||
fi
|
||
done
|
||
|
||
if (( current_dir_score >= current_max_score )) && (( current_dir_score > 50 )); then
|
||
current_max_score=${current_dir_score}
|
||
project_root=${current_dir}
|
||
fi
|
||
|
||
(( FIND_PROJECT_ROOT_DEBUG )) && echo -e "${depth} : ${current_dir}\n score : ${current_dir_score}"
|
||
|
||
current_dir=$(dirname "$current_dir")
|
||
((depth++))
|
||
done
|
||
|
||
# save data to cache
|
||
PROJECT_ROOT_CACHE[${cache_key}]="${project_root}"
|
||
|
||
if [[ "${project_root}" != "." ]]; then
|
||
PROJECT_ROOT="${project_root}"
|
||
return 0
|
||
fi
|
||
|
||
PROJECT_ROOT=""
|
||
return 1
|
||
}
|
||
|
||
declare -A DIR_MAJORITY_LANGUAGE_CACHE
|
||
export FIND_DIR_MAJORITY_LANGUAGE_DEBUG=0
|
||
|
||
find_dir_majority_language() {
|
||
local args=${@}
|
||
local cache_key="cache_$(echo -n $PWD | md5sum | cut -d' ' -f1)"
|
||
|
||
# args detection
|
||
for arg in ${args}; do
|
||
if [[ "${arg:0:2}" = "--" ]]; then
|
||
arg="${arg:2}"
|
||
|
||
case "${arg}" in
|
||
"help")
|
||
echo -e "Usage : find_dir_majority_language [OPTION(S)]\n"
|
||
echo "Find the majoritary language in the current and sub-folders."
|
||
echo "It is automatically called by the prompt generator but you can call it if you want to access or modify the cache.\n"
|
||
echo "The result is stocked in the env variable DIR_MAJORITY_LANGUAGE. The exit value is 0 when project root found or 1 if not."
|
||
echo "Options :"
|
||
echo " --print-cache print majority language cache"
|
||
echo " --clear-cache clear majority language cache ; WARNING : the cache is wiped automatically in new bash instances."
|
||
echo " --toggle-debug toggle debug mode"
|
||
echo " --help display this help"
|
||
return 0 ;;
|
||
|
||
"print-cache")
|
||
for key in ${!DIR_MAJORITY_LANGUAGE_CACHE[@]}; do
|
||
echo "[${key}]=${DIR_MAJORITY_LANGUAGE_CACHE[$key]}"
|
||
done ;;
|
||
|
||
"clear-cache")
|
||
DIR_MAJORITY_LANGUAGE_CACHE=() ;;
|
||
|
||
"toggle-debug")
|
||
FIND_DIR_MAJORITY_LANGUAGE_DEBUG=$((! FIND_DIR_MAJORITY_LANGUAGE_DEBUG)) ;;
|
||
|
||
*)
|
||
echo -e "Error : unrecognised parameter : --${arg}\n Try typing --help" ;;
|
||
esac
|
||
else
|
||
echo -e "Error : unrecognised parameter : ${arg}\n Try typing --help"
|
||
fi
|
||
done
|
||
|
||
# search cache for existing data
|
||
if [[ -n "${DIR_MAJORITY_LANGUAGE_CACHE[$cache_key]}" ]]; then
|
||
DIR_MAJORITY_LANGUAGE="${DIR_MAJORITY_LANGUAGE_CACHE[$cache_key]}"
|
||
return
|
||
fi
|
||
|
||
# in case of equal quantity of per-language file, the majoritary language is arbitrary selected
|
||
local C=0 Cpp=0 Rust=0 Go=0 Python=0 Java=0 Ruby=0 Javascript=0 PHP=0 CS=0 HTMLCSS=0 SQL=0
|
||
local ext=""
|
||
|
||
for file in "$PWD"/*.* "$PWD"/*/*.* "$PWD"/*/*/*.*; do
|
||
#[[ -f "$file" ]] || continue
|
||
local ext="${file##*.}"
|
||
[[ "${ext}" = "${file}" ]] && continue
|
||
|
||
case "${ext}" in
|
||
c|h) ((C++)) ;;
|
||
cpp|cxx|cc|hpp|hxx|hh|h) ((Cpp++)) ;;
|
||
rs|rlib) ((Rust++)) ;;
|
||
go) ((Go++)) ;;
|
||
py|pyw|pyc|pyo) ((Python++)) ;;
|
||
java|class|jar|war) ((Java++)) ;;
|
||
rb|erb|rake) ((Ruby++)) ;;
|
||
js|jsx|ts|tsx|mjs|cjs) ((Javascript++)) ;;
|
||
php|phtml) ((PHP++)) ;;
|
||
cs|csproj|sln) ((CS++)) ;;
|
||
html|htm|css|scss|sass|less)((HTMLCSS++)) ;;
|
||
esac
|
||
done
|
||
|
||
if (( FIND_DIR_MAJORITY_LANGUAGE_DEBUG )); then
|
||
echo "C: ${C}"
|
||
echo "C++: ${Cpp}"
|
||
echo "Rust: ${Rust}"
|
||
echo "Go: ${Go}"
|
||
echo "Python: ${Python}"
|
||
echo "Java: ${Java}"
|
||
echo "Ruby: ${Ruby}"
|
||
echo "Javascript: ${Javascript}"
|
||
echo "PHP: ${PHP}"
|
||
echo "C#: ${CS}"
|
||
echo "HTML/CSS: ${HTMLCSS}"
|
||
fi
|
||
|
||
local max_count=0
|
||
DIR_MAJORITY_LANGUAGE=""
|
||
|
||
(( C > max_count )) && max_count=${C} && DIR_MAJORITY_LANGUAGE="C"
|
||
(( Cpp > max_count )) && max_count=${Cpp} && DIR_MAJORITY_LANGUAGE="C++"
|
||
(( Rust > max_count )) && max_count=${Rust} && DIR_MAJORITY_LANGUAGE="Rust"
|
||
(( Go > max_count )) && max_count=${Go} && DIR_MAJORITY_LANGUAGE="Go"
|
||
(( Python > max_count )) && max_count=${Python} && DIR_MAJORITY_LANGUAGE="Python"
|
||
(( Java > max_count )) && max_count=${Java} && DIR_MAJORITY_LANGUAGE="Java"
|
||
(( Ruby > max_count )) && max_count=${Ruby} && DIR_MAJORITY_LANGUAGE="Ruby"
|
||
(( Javascript > max_count )) && max_count=${Javascript} && DIR_MAJORITY_LANGUAGE="Javascript"
|
||
(( PHP > max_count )) && max_count=${PHP} && DIR_MAJORITY_LANGUAGE="PHP"
|
||
(( CS > max_count )) && max_count=${CS} && DIR_MAJORITY_LANGUAGE="C#"
|
||
(( HTMLCSS > max_count )) && max_count=${HTMLCSS} && DIR_MAJORITY_LANGUAGE="HTML/CSS"
|
||
|
||
# save data to cache
|
||
DIR_MAJORITY_LANGUAGE_CACHE[${cache_key}]="${DIR_MAJORITY_LANGUAGE}"
|
||
}
|
||
|
||
gen_prompt() {
|
||
local LAST_EXIT_CODE=$?
|
||
|
||
local HOUR="\[\033[0;31m\]╭─\[\033[7;47m\]\A"
|
||
local USER="\[\033[45m\]\[\033[1;27;30m\]\u\[\033[7m\]"
|
||
local FOLDER="\[\033[0;36m\]\[\033[1;7m\]\w"
|
||
|
||
local INFO=" "
|
||
if find_project_root; then
|
||
find_dir_majority_language
|
||
local language_icon=" "
|
||
case "$DIR_MAJORITY_LANGUAGE" in
|
||
"C") language_icon=" " ;;
|
||
"C++") language_icon=" " ;;
|
||
"Rust") language_icon=" " ;;
|
||
"Go") language_icon=" " ;;
|
||
"Python") language_icon=" " ;;
|
||
"Java") language_icon=" " ;;
|
||
"Ruby") language_icon=" " ;;
|
||
"Javascript") language_icon=" " ;;
|
||
"PHP") language_icon=" " ;;
|
||
"C#") language_icon=" " ;;
|
||
"HTML/CSS") language_icon=" " ;;
|
||
esac
|
||
INFO="${language_icon}$(basename "${PROJECT_ROOT}")"
|
||
elif [ "$HOME" = "$PWD" ]; then
|
||
INFO=" "
|
||
elif [ "$HOME/${documents}" = "$PWD" ]; then
|
||
INFO=" "
|
||
elif [ "$HOME/${music}" = "$PWD" ]; then
|
||
INFO=" "
|
||
elif [ "$HOME/${pictures}" = "$PWD" ]; then
|
||
INFO=" "
|
||
elif [ "$HOME/${videos}" = "$PWD" ]; then
|
||
INFO=" "
|
||
elif [ "$HOME/${downloads}" = "$PWD" ]; then
|
||
INFO=" "
|
||
elif [ "$HOME/.config/" = "$PWD" ]; then
|
||
INFO=" "
|
||
elif [ "$HOME/.local/" = "$PWD" ]; then
|
||
INFO=" "
|
||
elif mount | grep -q "$PWD"; then
|
||
INFO=" "
|
||
fi
|
||
INFO="\[\033[45m\]\[\033[1;27;30m\]${INFO}\[\033[7m\]"
|
||
|
||
local ARROW_COLOR="35"
|
||
(( ${LAST_EXIT_CODE} != 0 )) && ARROW_COLOR="32"
|
||
local USER_PROMPT="\[\033[0;31m\]╰─\[\033[${ARROW_COLOR}m\]❯\[\033[0m\]"
|
||
|
||
PS1="\n${HOUR} ${USER} ${FOLDER} ${INFO}\n${USER_PROMPT} "
|
||
}
|
||
|
||
PROMPT_COMMAND=gen_prompt
|