├── .gitignore ├── visuals └── icon.png ├── binaries └── codeprofiles ├── new.sh ├── scripts └── compile_binary_deb.sh ├── uninstall.sh ├── install.sh ├── README.md └── profiles.sh /.gitignore: -------------------------------------------------------------------------------- 1 | *.sh.x.c -------------------------------------------------------------------------------- /visuals/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdallah-sameh-ragab/code-profiles/master/visuals/icon.png -------------------------------------------------------------------------------- /binaries/codeprofiles: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abdallah-sameh-ragab/code-profiles/master/binaries/codeprofiles -------------------------------------------------------------------------------- /new.sh: -------------------------------------------------------------------------------- 1 | SILENT_LAUNCH="false" 2 | LAUNCH_PROFILE="false" 3 | if $SILENT_LAUNCH && $LAUNCH_PROFILE; then 4 | echo "wtf man" 5 | fi -------------------------------------------------------------------------------- /scripts/compile_binary_deb.sh: -------------------------------------------------------------------------------- 1 | sudo apt-get install libc6-dev 2 | sudo apt-get install shc 3 | sudo shc -f profiles.sh -o binaries/codeprofiles 4 | -------------------------------------------------------------------------------- /uninstall.sh: -------------------------------------------------------------------------------- 1 | INSTALL_DIR="/opt/codeprofiles" 2 | BINARY_INSTALL_DIR="/usr/local/bin" 3 | 4 | sudo rm -rdf $INSTALL_DIR 5 | sudo rm -rdf "$BINARY_INSTALL_DIR/codeprofiles" 6 | sudo rm -rdf "/usr/share/applications/codeprofiles.desktop" -------------------------------------------------------------------------------- /install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | APP_DATA_DIR="$HOME/.codeprofiles/" 4 | PROFILES_DIR="$APP_DATA_DIR/profiles/" 5 | INSTALL_DIR="/opt/codeprofiles" 6 | BINARY_INSTALL_DIR="/usr/local/bin" 7 | CURRENT_DIR="$(pwd)" 8 | 9 | 10 | if [ -d "$INSTALL_DIR" ]; 11 | then 12 | rm -r $INSTALL_DIR 13 | fi 14 | sudo mkdir $INSTALL_DIR 15 | 16 | sudo cp "$CURRENT_DIR/profiles.sh" $INSTALL_DIR/ 17 | sudo chmod +x "$INSTALL_DIR/profiles.sh" 18 | 19 | sudo cp -R "$CURRENT_DIR/visuals/" "$INSTALL_DIR/" 20 | 21 | sudo chmod -R 777 "$INSTALL_DIR" 22 | # sudo chmod -R a=rw "$INSTALL_DIR/visuals" 23 | 24 | sudo cat > /usr/share/applications/codeprofiles.desktop << EOF 25 | [Desktop Entry] 26 | Version=1.0 27 | Type=Application 28 | Name=Code Profiles 29 | Comment=VS Code profile manager. 30 | Exec=bash $INSTALL_DIR/profiles.sh 31 | Icon=$INSTALL_DIR/visuals/icon.png 32 | Terminal=true 33 | StartupNotify=false 34 | EOF 35 | 36 | sudo chmod u+x /usr/share/applications/codeprofiles.desktop 37 | 38 | sudo cp "$CURRENT_DIR/binaries/codeprofiles" $BINARY_INSTALL_DIR/ 39 | sudo chmod +x "$BINARY_INSTALL_DIR/codeprofiles" 40 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # The Code Profiles | Multi-profile manager for VS Code. 2 | Simple tool to create and manage multiple profiles of vs code with different settings, themes and extensions. Essential for any developer that uses multiple languages with different setup for each one. 3 | 4 | ## Installation 5 | 6 | Simply run the installation script. 7 | 8 | sudo ./install.sh 9 | 10 | Make sure the script is executable by running the following command before running the installation script. 11 | 12 | chmod +x install.sh 13 | **Please note:** that the installation uses a pre-compiled binary included in the "binaries" folder, 14 | However you can compile your own binary using the script included in the "scripts" folder. make sure to replace the included binary with your own in the "binaries" folder before running the installation script. 15 | 16 | 17 | ## Usage 18 | 19 | Simply run the following command: 20 | 21 | codeprofiles [-p profile] [-s] [-h] 22 | ### Options: 23 | `-s` | Run in silent mode. if a profile is specified using the `-p` option the script will run VS Code with the specified profile and exit silently without showing the full interface. 24 | 25 | `-p [profile]` | Specify a profile to launch immediately as the script launches. 26 | 27 | `-h` | Get instructions. -------------------------------------------------------------------------------- /profiles.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | APP_DIR="$HOME/.codeprofiles/" 3 | PROFILES_DIR="$APP_DIR/profiles/" 4 | 5 | SILENT_LAUNCH="false" 6 | 7 | BRED='\033[1;91m' 8 | LRED='\033[1;31m' 9 | BGREEN="\033[1;92m" 10 | LGREEN='\033[1;32m' 11 | BBLUE="\033[1;94m" 12 | LBLUE='\033[1;34m' 13 | LYELLOW='\033[1;33m' 14 | BYELLOW='\033[1;93m' 15 | GRAY='\033[1;30m' 16 | LGRAY='\033[0;37m' 17 | BWHITE='\033[1;97m' 18 | LCYAN="\033[1;36m" 19 | BCYAN="\033[1;96m" 20 | MAGENTA="\033[1;95m" 21 | LMAGENTA="\033[1;35m" 22 | NC='\033[0m' 23 | 24 | 25 | GUIDE=" 26 | DESCRIPTON: 27 | The Code Profiles | Multi-profile manager for VS Code. 28 | Simple tool to create and manage multiple profiles of vs code. 29 | 30 | USAGE: 31 | $0 [-p profile] [-s] [-h] 32 | 33 | OPTIONS: 34 | -s Run in silent mode.if a profile is specified using the [-p] option the script will run VS Code with the specified profile and exit silently without showing the full interface. 35 | -p [profile] Specify a profile to launch immediately as the script launches. 36 | -h Get instructions. 37 | " 38 | 39 | render_app(){ 40 | 41 | if $SILENT_LAUNCH && [ ! -z ${LAUNCH_PROFILE+x} ]; then 42 | check_for_launch 43 | exit 44 | fi 45 | 46 | clear 47 | 48 | printf "${MAGENTA}> Welcome${BWHITE} $USER ${MAGENTA}:)\n\n${NC}" 49 | for err in "$@" ; do 50 | printf "$err \n" 51 | done 52 | if [[ ! -z $1 ]];then 53 | printf "\n" 54 | fi 55 | 56 | printf "${BWHITE}Choose a profile to start vs code:\n${NC}" 57 | render_profile_list 58 | render_options 59 | 60 | check_for_launch 61 | 62 | while :; 63 | do 64 | listen_for_keys 65 | done 66 | } 67 | check_for_launch(){ 68 | if [ ! -z ${LAUNCH_PROFILE+x} ];then 69 | launch_code $LAUNCH_PROFILE 70 | unset LAUNCH_PROFILE 71 | fi 72 | } 73 | check_dirs(){ 74 | if [ ! -d "$APP_DIR" ]; 75 | then 76 | sudo mkdir $APP_DIR 77 | fi 78 | sudo chmod 777 $APP_DIR 79 | 80 | if [ ! -d "$PROFILES_DIR" ]; 81 | then 82 | sudo mkdir $PROFILES_DIR 83 | fi 84 | sudo chmod 777 $PROFILES_DIR 85 | } 86 | render_profile_list(){ 87 | profiles_list 88 | if [[ ${#PROFILES_LIST[@]} == "0" ]];then 89 | printf "${BYELLOW} You don't have any profiles.\n" 90 | printf " Press ${BWHITE}N${BYELLOW} to create a new profile.\n${NC}" 91 | fi 92 | for P in ${!PROFILES_LIST[@]};do 93 | printf " ${BBLUE}[$P]${LGRAY} ${PROFILES_LIST[P]}\n${NC}" 94 | done 95 | printf "\n" 96 | } 97 | profiles_list(){ 98 | PROFILES_STRING=$(echo $(read_profiles) | tr " " ",") 99 | IFS=',' read -r -a PROFILES_LIST <<< "$PROFILES_STRING" 100 | } 101 | read_profiles(){ 102 | for DIR in $(ls $PROFILES_DIR); do 103 | if [[ -d $PROFILES_DIR/$DIR ]];then 104 | echo "$DIR" 105 | fi 106 | done 107 | } 108 | render_options(){ 109 | printf "${BWHITE}Choose another option:\n${NC}" 110 | printf " ${BGREEN}[N]${NC} Create a new profile\n" 111 | printf " ${BGREEN}[D]${NC} Delete a profile\n" 112 | printf " ${BGREEN}[Q]${NC} Quit\n" 113 | } 114 | listen_for_keys(){ 115 | read -rsn1 input 116 | 117 | if $(key_exists_in_profiles $input);then 118 | USER_CHOSEN_PROFILE=${PROFILES_LIST[$input]} 119 | launch_code $USER_CHOSEN_PROFILE 120 | elif [[ $input = "n" ]] || [[ $input = "N" ]];then 121 | handle_new_profile_name 122 | elif [[ $input = "q" ]] || [[ $input = "Q" ]];then 123 | printf "${BYELLOW}\nAre you sure you want to exit?\n${NC}" 124 | printf "[${BWHITE}Y${NC} to confirm ${BWHITE}N${NC} to cancel]\n" 125 | while :;do 126 | read -rsn1 conf 127 | if [[ $conf = "y" ]] || [[ $conf = "Y" ]]; then 128 | exit 129 | elif [[ $conf = "n" ]] || [[ $conf = "N" ]]; then 130 | render_app 131 | fi 132 | done 133 | elif [[ $input = "d" ]] || [[ $input = "D" ]];then 134 | if [[ ${#PROFILES_LIST[@]} == "0" ]];then 135 | render_app "${LRED}Error:${BRED} You don't have any profiles to delete.${NC}" 136 | fi 137 | handle_delete_profile 138 | fi 139 | } 140 | key_exists_in_profiles(){ 141 | re='^[0-9]+$' 142 | if ! [[ $1 =~ $re ]] ; then 143 | echo "false" 144 | else 145 | if [ -v PROFILES_LIST[$1] ];then 146 | echo "true" 147 | else 148 | echo "false" 149 | fi 150 | fi 151 | } 152 | launch_code(){ 153 | local PROFILE=$1 154 | local PROFILE_DIR="$PROFILES_DIR/$PROFILE" 155 | printf "\n${BYELLOW}launching${BWHITE} $PROFILE ${BYELLOW}... ${NC}" 156 | code --user-data-dir $PROFILE_DIR/data --extensions-dir $PROFILE_DIR/extensions 157 | if [[ $? = "0" ]];then 158 | printf "${BGREEN}Done${NC}" 159 | else 160 | printf "${BRED}Failed${NC}" 161 | fi 162 | } 163 | handle_new_profile_name(){ 164 | clear 165 | 166 | printf "${BWHITE}Creating a new profile for you.\n\n${NC}" 167 | 168 | for err in "$@" ; do 169 | printf "$err \n" 170 | done 171 | if [[ ! -z $1 ]];then 172 | printf "\n" 173 | fi 174 | 175 | set -o emacs 176 | bind '"\C-w": kill-whole-line' 177 | bind '"\e": "\C-w\C-d"' 178 | bind '"\e\e": "\C-w\C-d"' 179 | printf "What do you want to call the profile ? (${BWHITE}ESC${NC} to return): " 180 | IFS= read -rep '' NEW_PROFILE_INPUT || { 181 | render_app 182 | } 183 | 184 | local PROFILE_EXISTS=$(check_if_profile_exists $NEW_PROFILE_INPUT) 185 | local PROFILE_VALID=$(check_if_profile_name_is_valid $NEW_PROFILE_INPUT) 186 | 187 | if [[ -z "${NEW_PROFILE_INPUT// }" ]];then 188 | handle_new_profile_name "${LRED}Error:${BRED} profile name can't be empty.${NC}" 189 | fi 190 | 191 | if $PROFILE_EXISTS;then 192 | handle_new_profile_name "${LRED}Error:${BRED} '$NEW_PROFILE_INPUT' already exists.${NC}" 193 | else 194 | if $PROFILE_VALID;then 195 | add_profile $NEW_PROFILE_INPUT 196 | else 197 | handle_new_profile_name "${LRED}Error:${BRED} profile name is not valid." "Allowed characters [Alphabetical letters, Numbers, '_' and '-']." "Whitespaces are not allowed.${NC}" 198 | fi 199 | fi 200 | 201 | } 202 | add_profile(){ 203 | mkdir "$PROFILES_DIR/$1" 204 | if [[ $? = "0" ]];then 205 | render_app 206 | else 207 | render_app "${LRED}Error:${BRED} profile creation failed. Make sure you have the right permissions to create directories.${NC}" 208 | fi 209 | } 210 | handle_delete_profile(){ 211 | clear 212 | 213 | printf "${BWHITE}Choose a profile to delete:\n${NC}" 214 | render_profile_list 215 | 216 | for err in "$@" ; do 217 | printf "$err \n" 218 | done 219 | if [[ ! -z $1 ]];then 220 | printf "\n" 221 | fi 222 | 223 | set -o emacs 224 | bind '"\C-w": kill-whole-line' 225 | bind '"\e": "\C-w\C-d"' 226 | bind '"\e\e": "\C-w\C-d"' 227 | printf "choose a profile from the list (${BWHITE}ESC${NC} to return):" 228 | IFS= read -rep "" DELETE_PROFILE_NAME || { 229 | render_app 230 | } 231 | DELETE_PROFILE_NAME=${DELETE_PROFILE_NAME// } 232 | if $(key_exists_in_profiles $DELETE_PROFILE_NAME);then 233 | DELETE_PROFILE_NAME=${PROFILES_LIST[DELETE_PROFILE_NAME]} 234 | elif $(check_if_profile_exists $DELETE_PROFILE_NAME);then 235 | DELETE_PROFILE_NAME=$DELETE_PROFILE_NAME 236 | else 237 | handle_delete_profile "${LRED}Error:${BRED} profile does not exist." "Make sure to enter the correct profile name or number from the list above.${NC}" 238 | fi 239 | 240 | printf "${BYELLOW}\nAre you sure you want to delete ${BWHITE}'$DELETE_PROFILE_NAME'${BYELLOW} permanently? \n${NC}" 241 | printf "${BRED}All the extentions and user data of this profile will be forever lost.\n${NC}" 242 | printf "[Press ${BWHITE}Y${NC} to confirm or ${BWHITE}N${NC} to cancel]\n" 243 | while :;do 244 | read -rsn1 conf 245 | if [[ $conf = "y" ]] || [[ $conf = "Y" ]]; then 246 | delete_profile $DELETE_PROFILE_NAME 247 | render_app 248 | elif [[ $conf = "n" ]] || [[ $conf = "N" ]]; then 249 | render_app 250 | fi 251 | done 252 | } 253 | delete_profile(){ 254 | sudo rm -rfd bash "$PROFILES_DIR/$1" 255 | } 256 | check_if_profile_exists(){ 257 | IFS=',' 258 | if [[ "${IFS}${PROFILES_STRING[*]}${IFS}" =~ "${IFS}${1}${IFS}" ]]; then 259 | echo "true" 260 | else 261 | echo "false" 262 | fi 263 | unset IFS 264 | } 265 | check_if_profile_name_is_valid(){ 266 | if [[ "$1" =~ [^A-Za-z0-9_-] ]];then 267 | echo "false" 268 | else 269 | echo "true" 270 | fi 271 | 272 | } 273 | 274 | check_dirs 275 | 276 | if [ $1 = "--help" ];then 277 | echo "$GUIDE" 278 | exit 279 | fi 280 | 281 | while getopts "shp:" arg; do 282 | case $arg in 283 | h) 284 | echo "$GUIDE" 285 | exit 286 | ;; 287 | s) 288 | SILENT_LAUNCH="true" 289 | ;; 290 | p) 291 | profiles_list 292 | if $(check_if_profile_exists $OPTARG);then 293 | LAUNCH_PROFILE=$OPTARG 294 | render_app 295 | else 296 | render_app "${LRED}Error:${BRED} profile ${BWHITE}'$OPTARG'${BRED} was not found.${NC}" 297 | fi 298 | 299 | ;; 300 | esac 301 | done 302 | 303 | 304 | 305 | render_app 306 | 307 | 308 | --------------------------------------------------------------------------------