[v1.0.0] Big release! :)

This commit is contained in:
yage 2022-01-03 15:08:13 -07:00
parent c6ddebe301
commit a9f2fe51ad
18 changed files with 570 additions and 501 deletions

29
.env.zsh Normal file
View File

@ -0,0 +1,29 @@
#####################################################################
# code-activator artifact #
#####################################################################
# #
# Variables and functions set in this file will be sourced when #
# this project is activated #
# #
# #
# Using the following syntax: #
# ``` #
# __RESTORE__ENV_VAR='new-value' #
# ``` #
# will save the current value of $ENV_VAR then assign ENV_VAR to #
# the 'new-value'. When code-activator calls deactivate, ENV_VAR #
# will be reset to its original value. #
# #
# this only works with VARIABLES (not functions) #
# #
# #
# #
# all other variables / functions will simply be unset whenever: #
# - deactivate is called #
# - another project is activated #
# #
#####################################################################
export __RESTORE__PATH="$PATH"
export MY_EXAMPLE_VARIABLE=69

View File

@ -1,65 +1,44 @@
# Code Activator
##### *A `zsh` utility for terminal-based project navigation*
[![Generic badge](https://img.shields.io/badge/junegunn-fzf-blueviolet.svg)](https://github.com/junegunn/fzf)
[![Generic badge](https://img.shields.io/badge/stedolan-jq-blueviolet.svg)](https://github.com/jq/)
The `CODE_ACTIVATOR` function facilitates terminal-based project navigation by providing an interactive, fuzzy-search CLI.
Generally, the CLI will activate a project's virtual environment then step into the project root.
Once inside a project, the CLI gives the option to deactivate and return to the user's home directory.
Projects can also be quickly cloned or created from scratch by using the `clone` and `new` operations respectively.
Use the plugin one of three ways:
1. Use the shortcut combination (`CTRL+SPACE` by default)
1. Use the alias (`lkj` by default)
1. Call `CODE_ACTIVATOR` directly (meant for use as an API)
Code Activator provides fast project navigation in the terminal through both an API and CLI.
## Contributing
See our [contributing guide](./docs/CONTRIBUTING.md) and [code of conduct](./docs/CODE_OF_CONDUCT.md).
## Installation
1. install [junegunn/fzf](https://github.com/junegunn/fzf)
1. clone this repo, and source the `*.plugin.zsh` in your `zshrc`:
1. install dependencies [junegunn/fzf](https://github.com/junegunn/fzf) and [stedolan/jq](https://github.com/stedolan/jq)
1. clone this repo, and source the `activator.plugin.zsh` in your `zshrc`:
```shell
# replace <path-to>/code-activator with the appropriate path
git clone https://github.com/w0ryn/code-activator-zsh.git <path-to>/code-activator
echo 'source <path-to>/code-activator' >> $HOME/.zshrc
```
## Configuration
All configuration options are determined by their respective environment variables.
By default, Code Activator looks for projects in `~/Projects/GitHub` and `~/Projects/BitBucket`, but you can configure\* this in your `~/.config/code-activator-zsh/settings.zsh`.
It is highly recommended that, if nothing else, you configure `CA__DIRS` to group your projects as you please.
### Basic Configuration
Environment Variable | Default | Description
---------------------------------- | ------------------------------- | -----------
`CODE_ACTIVATOR__SHORTCUT` | `^@` (a.k.a. CTRL+SPACE) | shortcut for running `CODE_ACTIVATOR` as a plugin
`CODE_ACTIVATOR__DISABLE_SHORTCUT` | `0` (a.k.a. false) | whether (or not) the shortcut runner is disabled
`CODE_ACTIVATOR__ALIAS` | `lkj` | easy-to-type alias for running `CODE_ACTIVATOR`
`CODE_ACTIVATOR__DISABLE_ALIAS` | `0` (a.k.a. false) | whether (or not) the alias runner is disabled
<sup>\**the configuration file is created the first time Code Activator is sourced*</sup>
### Project Directories
- `CODE_ACTIVATOR__DIRS` (list) environment variable
A list of fully-qualified paths to project parent directories.
Provides `($HOME/Code)` as a generic default, but allows for meaningful project grouping:
```shell
export CODE_ACTIVATOR__DIRS=(
"$HOME/Company/Team1"
"$HOME/Company/Team2"
"$HOME/Miscellaneous"
"$HOME/Personal"
)
```
## Usage
Code Activator commands can be invoked one of three ways:
1. directly (`code-activator`; intended for use as an API)
2. through an alias (`lkj` by default)
3. through a shortcut (`CTRL+SPACE` by default; creates a zsh-plugin)
### Known Targets
- `CODE_ACTIVATOR__KNOWN_TARGETS` (list) environment variable
- expects targets to end in `:` or `/` character
- *appends environment variable list to the default list*
With no argument, Code Activator provides a list of all available projects.
Select one to activate it's environment and jump to the project's root.
If your first argument to Code Activator is a project name, the specified project will be activated.
You can also `deactivate` an activated project, `clone` an existing project, or create a `new` project (with the appropriate command).
## Custom Environment
Although not exactly a virtual environment, Code Activator creates a `custom-env` for projects where you can set project-specific environment variables or shell functions.
It also provides a `__RESTORE__` syntax to allow safe manipulation of `PATH` or other variables when activating a project.
See [the custom-env template](./.env.zsh) for more details.
A list of default completion targets for setting up or cloning new repositories.
Includes HTTP and GIT protocol targets for GitHub and BitBucket by default, but you may want to add your user to the list:
```shell
export CODE_ACTIVATOR__KNOWN_TARGETS=(
'git@github.com:<your-username>/'
)
```

23
activator.bindings.zsh Normal file
View File

@ -0,0 +1,23 @@
#####################################################################
[[ $CA__DISABLE_ALIAS -eq 0 ]] && {
alias $CA__ALIAS='code-activator'
}
#####################################################################
[[ $CA__DISABLE_SHORTCUT -eq 0 ]] && command -v zle >/dev/null 2>&1 \
|| return 0
_CA__ZSH_SHORTCUT_PLUGIN() {
local OPTIONS=(clone new $(_CA_LIST))
[ $_CA_ENV ] && OPTIONS=(deactivate $OPTIONS)
local SELECTION=$(echo $OPTIONS | _CA_MULTILINE | _CA_FZF 'select a project')
[[ $SELECTION =~ . ]] && code-activator $SELECTION
echo
zle reset-prompt
}
zle -N codeactivator _CA__ZSH_SHORTCUT_PLUGIN
bindkey $CA__SHORTCUT codeactivator

40
activator.completion.zsh Normal file
View File

@ -0,0 +1,40 @@
#####################################################################
command -v compdef >/dev/null 2>&1 || return 0
#####################################################################
_CA__PROJECT_COMPADD() {
local DESCRIPTIONS=()
[ $_CA_ENV ] && DESCRIPTIONS+='deactivate:deactivate env and jump to $HOME'
DESCRIPTIONS+='clone:clone a project from a known target'
DESCRIPTIONS+='new:create a new project'
_describe 'commands' DESCRIPTIONS
compadd -- $(_CA_LIST)
}
#####################################################################
_code-activator() {
local state
_arguments \
'1: :->project' \
'2: :->arg1' \
;
case $state in
project ) _CA__PROJECT_COMPADD ;;
arg1 )
case $words[2] in
clone )
echo; echo 'where should I clone this?'
compadd -- $CA__DIRS
;;
esac
;;
esac
}
compdef _code-activator code-activator

View File

@ -1,131 +1,40 @@
#!/bin/zsh
#####################################################################
###################################################################
# #
# CODE_ACTIVATOR : a terminal-based navigation utility #
# code-activator() : a terminal-based navigation utility #
# #
#####################################################################
###################################################################
DEPENDENCIES=(
fzf
)
IMPORTS=(
"${0:a:h}/zsh/settings.zsh"
"${0:a:h}/zsh/helpers.zsh"
"${0:a:h}/zsh/clone.zsh"
"${0:a:h}/zsh/activate.zsh"
)
_CA__VERSION=1.0.0
_CA__DEPENDENCIES=(code-activator fzf jq git)
#####################################################################
for DEPENDENCY in $DEPENDENCIES
do
command -v $DEPENDENCY >/dev/null 2>&1 || {
echo "I require '$DEPENDENCY' but it's not installed :c"
ERROR_CODE=1
}
done
export _CA=${0:a:h}
source $_CA/global.zsh || return 1
source $_CA/config.zsh || return 1
for Z in $(ls $_CA/zsh/*); do source $Z || return 1; done
#####################################################################
for IMPORT in $IMPORTS; do source $IMPORT; done
code-activator() {
_CA__CHECK_DEPENDENCIES $_CA__DEPENDENCIES || return 1
[ ! $_CA__ACTIVATE_LOADED ] && ERROR_CODE=2
[ ! $_CA__CLONE_LOADED ] && ERROR_CODE=2
#####################################################################
[ $ERROR_CODE ] && return $ERROR_CODE
#####################################################################
#####################################################################
CODE_ACTIVATOR() {
local ERROR=0
local COMMAND ARGS
case $1 in
deactivate ) _CA__RESTORE_ENVIRONMENT && cd || ERROR=1 ;;
deactivate ) COMMAND=DEACTIVATE ;;
clone ) _CA__CLONE ${@:2} || ERROR=1 ;;
new ) IS_NEW_PROJECT=1 _CA__CLONE ${@:2} || ERROR=1 ;;
* ) _CA__ACTIVATE ${@:1} || ERROR=42 ;;
clone ) COMMAND=CLONE; ARGS=(${@:2}) ;;
new ) COMMAND=NEW; ARGS=(${@:2}) ;;
* ) COMMAND=ACTIVATE; ARGS=(${@:1}) ;;
esac
[[ $ERROR -ne 0 ]] && _CA__ERROR_CLEANUP $ERROR
return $ERROR
_CA_$COMMAND $ARGS
}
_CODE_ACTIVATOR() {
local state
_arguments \
'1: :->project' \
':: :->arguments' \
;
case $state in
project )
compadd $(_CA__GET_COMMANDS_AND_PROJECTS | sed 's/deactivate//')
;;
arguments )
case $words[2] in
clone ) __CA__CLONE ;;
esac
;;
esac
}
compdef _CODE_ACTIVATOR CODE_ACTIVATOR
#####################################################################
_CA__GET_COMMANDS_AND_PROJECTS() {
local COMMANDS=(deactivate clone new)
local PROJECTS=()
for base_dir in $CODE_ACTIVATOR__DIRS
do
for project_dir in $(ls -d -- $base_dir/*)
do
PROJECTS+=("$(basename $base_dir)/$(basename $project_dir)")
done
done
echo $COMMANDS $PROJECTS
}
_CA__ERROR_CLEANUP() {
local ERROR="$1"
[ $_CA__SUPPRESS_ERROR ] && return
case $ERROR in
42 )
echo 'failed to activate environment; aborting' >&2
;;
esac
}
#####################################################################
[[ $CODE_ACTIVATOR__DISABLE_SHORTCUT -eq 0 ]] && {
_CA__ZSH_SHORTCUT_PLUGIN() {
local OPTIONS=$(_CA__GET_COMMANDS_AND_PROJECTS | _CA__SED_MULTILINE)
[ ! $__CUSTOM_ENV_ACTIVE ] && OPTIONS=$(echo $OPTIONS | grep -v 'deactivate')
local ARGUMENT=$(\
echo $OPTIONS \
| _CA__SED_MULTILINE \
| $_CA__FZF --prompt 'select a project: ' \
)
_CA__IN_ZSH_PLUGIN=1 CODE_ACTIVATOR $ARGUMENT
echo
zle reset-prompt
}
zle -N codeactivator _CA__ZSH_SHORTCUT_PLUGIN
bindkey $CODE_ACTIVATOR__SHORTCUT codeactivator
}
[[ $CODE_ACTIVATOR__DISABLE_ALIAS -eq 0 ]] && {
alias $CODE_ACTIVATOR__ALIAS='CODE_ACTIVATOR'
}
source $_CA/activator.completion.zsh
source $_CA/activator.bindings.zsh

67
config.zsh Normal file
View File

@ -0,0 +1,67 @@
# cloned projects will be nested under the specified directories,
# allowing for meaningful project grouping. A friendly name is
# derived from the path
#
# e.g. "$HOME/Projects/GitHub" will be called "GitHub" in the CLI
#
# directories must be fully-qualified
CA__DIRS=(
"$HOME/Projects/GitHub"
"$HOME/Projects/BitBucket"
)
# additional cloning targets; MUST END IN ':' or '/'
# e.g. 'git@my.githost.com:' or 'git@github.com:w0ryn/'
CA__KNOWN_TARGETS=(
'https://github.com/'
'https://bitbucket.org/'
'git@github.com:'
'git@bitbucket.org:'
)
# run from the specified hot-key
CA__SHORTCUT='' # CTRL+SPACE
# run from the specified alias
CA__ALIAS='lkj'
# enable / disable the shortcut / alias
# 0 = enabled 1 = disabled
CA__DISABLE_SHORTCUT=0
CA__DISABLE_ALIAS=0
# structure options
#
# where LOCAL_PROJECT_NAME is provided through the API / CLI,
# the plugin will attempt to create the following structure:
#
# LOCAL_PROJECT_NAME
# | SOURCE_DIR << cloned repository
# | VIRTUAL_ENV << the project's virtual environment
# | CUSTOM_ENV << CODE_ACTIVATOR's custom environment variables file
# | NO_ENV << CODE_ACTIVATOR sentinel to avoid prompting env setup
CA__SOURCE_DIR='code'
CA__VIRTUAL_ENV='env'
CA__CUSTOM_ENV='custom-env'
CA__NO_ENV='no-env'
#####################################################################
[ ! -f $_CA__LOCAL_CONFIG ] && {
mkdir -p -- $(dirname $_CA__LOCAL_CONFIG) >/dev/null 2>&1
awk '/##/{exit};1' $_CA/config.zsh | sed 's/^[^#]/#&/; $d'> $_CA__LOCAL_CONFIG
}
source $_CA__LOCAL_CONFIG
export \
CA__DIRS \
CA__KNOWN_TARGETS \
CA__SOURCE_DIR_NAME \
CA__VIRTUAL_ENV_NAME \
CA__CUSTOM_ENV_NAME \
CA__NO_ENV \
;

59
global.zsh Normal file
View File

@ -0,0 +1,59 @@
#####################################################################
### Artifacts and Operations ########################################
#####################################################################
_CA__LOCAL_CONFIG="$HOME/.config/code-activator-zsh/settings.zsh"
_CA_ERROR() { [ $_CA__SUPPRESS_ERROR ] || echo "CA::ERROR : $@" >&2; }
_CA_FZF() {
local MSG="$@"
[ ! $_NOSEP ] && MSG="$@ : "
fzf -i --height=50% --layout=reverse $FLAGS --prompt $MSG
}
_CA_FZF_PRINT() { _NOSEP=$_NOSEP FLAGS=(--print-query) _CA_FZF $@ | tail -1; }
_CA_LOAD() { source $_CA/zsh/$1.zsh; }
_CA_READ() { read -k $1; echo; }
_CA_MULTILINE() { sed 's/\s\+/\n/g'; }
_CA_LIST() {
local base_dir PROJECTS=()
{
for base_dir in $CA__DIRS
do
{ cd $base_dir; ls -d *; } \
| awk '{print "'$(basename $base_dir)/'"$1;}'
done
}
}
#####################################################################
### Dependency Checking #############################################
#####################################################################
_CA__CHECK_DEPENDENCIES() {
local D DEPENDENCIES=($@)
for D in $DEPENDENCIES
do
command -v $D >/dev/null 2>&1 || {
local LINK=$(_CA__GET_DEPENDENCY_LINK $D)
echo "I require '$D', but it's not installed. $LINK" >&2
}
done
}
_CA__GET_DEPENDENCY_LINK() {
local LINK
case $1 in
fzf ) LINK='https://github.com/junegunn/fzf' ;;
jq ) LINK='https://github.com/stedolan/jq' ;;
esac
[ $LINK ] && LINK='('$LINK')'
echo $LINK
}

View File

@ -1,58 +1,33 @@
#####################################################################
[ ! $_CA__SETTINGS_LOADED ] && source "${0:a:h}/settings.zsh"
[ ! $_CA__HELPERS_LOADED ] && source "${0:a:h}/helpers.zsh"
#####################################################################
_CA__ACTIVATE() {
_CA__RESTORE_ENVIRONMENT
_CA_ACTIVATE() {
local PROJECT="$1"
[ ! $PROJECT ] && {
[ ! $_CA__IN_ZSH_PLUGIN ] && cd
return 0
}
[ ! $PROJECT ] && return 1
local PROJECT_PATH=$(_CA__GET_FULL_PATH $PROJECT)
[ ! -d $PROJECT_PATH ] && return 1
local SOURCE_PATH="$PROJECT_PATH/$_CA__SOURCE_DIR_NAME"
[ -d $SOURCE_PATH ] && {
_CA__ACTIVATE_VIRTUAL_ENV $PROJECT_PATH
_CA__ACTIVATE_CUSTOM_ENV $PROJECT_PATH
cd $SOURCE_PATH
} || {
export __CUSTOM_ENV_ACTIVE=420
cd $PROJECT_PATH
}
_CA__TMUX_WINDOW_RENAME $PROJECT
_CA_ACTIVATE_ENV $PROJECT_PATH
return 0
}
_CA__ACTIVATE_VIRTUAL_ENV() {
local PROJECT_PATH="$1"
local ACTIVATE="$PROJECT_PATH/$_CA__VIRTUAL_ENV_NAME/bin/activate"
local NO_ENV="$PROJECT_PATH/$_CA__NO_ENV_SENTINEL"
_CA__GET_FULL_PATH() {
local PROJECT="$1"
[ -f $ACTIVATE ] && {
source $ACTIVATE
} || {
[ ! -f $NO_ENV ] && {
_CA__INTERACTIVE_ENV_SETUP $PROJECT_PATH && source $ACTIVATE
}
}
}
local PROJECT_ROOT_SHORT=$(dirname $PROJECT)
local PROJECT_NAME=$(basename $PROJECT)
_CA__ACTIVATE_CUSTOM_ENV() {
local PROJECT_PATH="$1"
local CUSTOM_ENV="$PROJECT_PATH/$_CA__CUSTOM_ENV_NAME"
local FULL_BASE_DIR=$(\
echo $CA__DIRS \
| _CA_MULTILINE \
| grep "^.*/$PROJECT_ROOT_SHORT$" \
)
[ ! -f $CUSTOM_ENV ] && _CA__INIT_CUSTOM_ENV $PROJECT_PATH
source $CUSTOM_ENV
echo "$FULL_BASE_DIR/$PROJECT_NAME"
}
#####################################################################
export _CA__ACTIVATE_LOADED=1
_CA_DEACTIVATE() {
_CA_RESTORE_ENV
cd
}

View File

@ -1,12 +1,7 @@
#####################################################################
_CA_NEW() { IS_NEW=1 _CA_CLONE_OR_NEW $@; }
_CA_CLONE() { IS_NEW=0 _CA_CLONE_OR_NEW $@; }
[ ! $_CA__SETTINGS_LOADED ] && source "${0:a:h}/settings.zsh"
[ ! $_CA__HELPERS_LOADED ] && source "${0:a:h}/helpers.zsh"
[ ! $_CA__ACTIVATE_LOADED ] && source "${0:a:h}/activate.zsh"
#####################################################################
_CA__CLONE() {
_CA_CLONE_OR_NEW() {
local BASE_DIR="$1"
local REMOTE_TARGET="$2"
local PROJECT_NAME="$3"
@ -16,7 +11,7 @@ _CA__CLONE() {
[ ! $REMOTE_TARGET ] && REMOTE_TARGET=$(_CA__GET_REMOTE_TARGET)
[ ! $REMOTE_TARGET ] && return 1
echo $REMOTE_TARGET
[[ $REMOTE_TARGET =~ .git$ ]] || return 1
[ ! $PROJECT_NAME ] && PROJECT_NAME=$(_CA__GET_PROJECT_NAME $REMOTE_TARGET)
@ -24,80 +19,8 @@ _CA__CLONE() {
local PROJECT_PATH="$BASE_DIR/$PROJECT_NAME"
[ -d $PROJECT_PATH ] && {
echo "project '$PROJECT_NAME' already exists in '$(basename $BASE_DIR)'"
return 1
}
mkdir $PROJECT_PATH
_CA__CLONE_SOURCE $REMOTE_TARGET $PROJECT_PATH $IS_NEW_PROJECT
_CA__INIT_CUSTOM_ENV $PROJECT_PATH
[[ $IS_NEW -eq 0 ]] && _CA__GIT_CLONE $PROJECT_PATH $REMOTE_TARGET
[[ $IS_NEW -eq 1 ]] && _CA__GIT_INIT $PROJECT_PATH $REMOTE_TARGET
_CA__ACTIVATE "$(basename $BASE_DIR)/$PROJECT_NAME"
_CA_ACTIVATE "$(basename $BASE_DIR)/$PROJECT_NAME"
}
__CA__CLONE() {
local state
_arguments \
'1: :->base_dir' \
'2: :->project_name' \
'3: :->remote_target' \
':: :->arguments' \
;
case $state in
base_dir )
for dir in $CODE_ACTIVATOR__DIRS; do compadd $dir; done
;;
project_name )
;;
remote_target )
;;
arguments ) ;;
esac
}
#####################################################################
_CA__CLONE_SOURCE() {
local REMOTE_TARGET="$1"
local PROJECT_PATH="$2"
local IS_NEW_PROJECT="$3"
local SOURCE_DIR="$PROJECT_PATH/$_CA__SOURCE_DIR_NAME"
echo "trying to clone '$REMOTE_TARGET' to '$PROJECT_PATH'"
git clone "$REMOTE_TARGET" "$SOURCE_DIR" >/dev/null 2>&1 || {
echo "failed to clone '$REMOTE_TARGET'"
[ ! $IS_NEW_PROJECT ] && {
printf "is this a new project? [y/N]"
_CA__READ_K yn
[[ $yn =~ ^[yY] ]] && IS_NEW_PROJECT=1
}
[ $IS_NEW_PROJECT ] && {
printf 'initializing project...'
{
mkdir $SOURCE_DIR \
&& cd $SOURCE_DIR \
&& git init \
&& touch .gitignore \
&& git add .gitignore \
&& git commit -m 'project init' \
&& git remote add $_CA__GET_GIT_MAIN_BRANCH $REMOTE_TARGET \
&& cd .. \
;
} >/dev/null >&1 && echo ' success :)' || echo ' failed :c'
} || {
rm -rf -- $PROJECT_PATH
echo 'exiting'
return 1
}
}
}
#####################################################################
export _CA__CLONE_LOADED=1

View File

@ -1,13 +0,0 @@
#####################################################################
# Store initial PATH; allows for safe PATH manipulation for a particular project
export _CA__RESTORE_PATH="$PATH"
# Store a list of project-specific environment variables; unset on env exit
export _CA__RESTORE_ENV=(
__CUSTOM_ENV_ACTIVE
)
#####################################################################
export __CUSTOM_ENV_ACTIVE=69

46
zsh/env-activate.zsh Normal file
View File

@ -0,0 +1,46 @@
_CA_ACTIVATE_ENV() {
local PROJECT_PATH="$1"
local SOURCE_PATH="$PROJECT_PATH/$CA__SOURCE_DIR"
_CA_RESTORE_ENV
export _CA_ENV=$PROJECT_PATH/$CA__CUSTOM_ENV
[ -d $SOURCE_PATH ] && {
_CA__CUSTOM_ENV_INIT
_CA__CUSTOM_ENV_SET_VARIABLES $PROJECT_PATH
_CA__ENV__ACTIVATE $PROJECT_PATH
cd $SOURCE_PATH
} || {
cd $PROJECT_PATH
}
_CA__TMUX_WINDOW_RENAME $PROJECT
}
_CA__ENV__ACTIVATE() {
local PROJECT_PATH="$1"
local NO_ENV="$PROJECT_PATH/$CA__NO_ENV"
local ACTIVATE="$PROJECT_PATH/$CA__VIRTUAL_ENV/bin/activate"
[ -f $ACTIVATE ] && {
source $ACTIVATE
} || {
[ ! -f $NO_ENV ] && {
_CA__INTERACTIVE_ENV_SETUP $PROJECT_PATH && source $ACTIVATE
}
}
}
#####################################################################
_CA_RESTORE_ENV() {
deactivate >/dev/null 2>&1
deactivate_node >/dev/null 2>&1
_CA__CUSTOM_ENV_UNSET_VARIABLES
_CA__TMUX_RESTORE_WINDOW_NAME
unset _CA_ENV
}

65
zsh/env-custom.zsh Normal file
View File

@ -0,0 +1,65 @@
_CA__CUSTOM_ENV_SET_VARIABLES() {
[ $_CA_ENV ] && [ -f $_CA_ENV ] || return
local env_var
for env_var in $(_CA__CUSTOM_ENV_GET_RESTORE_NAMES)
do
eval 'export __RESTORE__'$env_var'=$'$env_var
done
eval "$(sed 's/__RESTORE__//g' $_CA_ENV)"
}
_CA__CUSTOM_ENV_UNSET_VARIABLES() {
[ $_CA_ENV ] && [ -f $_CA_ENV ] || return
local var
for var in $(_CA__CUSTOM_ENV_GET_VARIABLE_NAMES)
do
[[ ! $var =~ ^PATH$ ]] && unset $var
done
for var in $(_CA__CUSTOM_ENV_GET_FUNCTION_NAMES)
do
unset -f $var
done
for var in $(_CA__CUSTOM_ENV_GET_RESTORE_NAMES)
do
eval 'export '$var'=$__RESTORE__'$var
unset __RESTORE__$var
done
for var in $(_CA__CUSTOM_ENV_GET_FUNCTION_NAMES)
}
_CA__CUSTOM_ENV_INIT() {
[ ! -f $_CA_ENV ] && {
cp "$_CA/.env.zsh" $_CA_ENV
}
}
#####################################################################
_CA__CUSTOM_ENV_GET_VARIABLE_NAMES() {
grep -- '^[^#][^=]*=.' $_CA_ENV \
| _CA_SED__VARIABLE_NAME | sort -u
}
_CA__CUSTOM_ENV_GET_FUNCTION_NAMES() {
{
grep -- '^function ' $_CA_ENV | sed 's/function //'
grep -- '[^ #]*()' $_CA_ENV
} | sed 's/().*//' | sort -u
}
_CA__CUSTOM_ENV_GET_RESTORE_NAMES() {
grep -- '^[^#][^=]*=.' $_CA_ENV | grep '__RESTORE__' \
| _CA_SED__VARIABLE_NAME | sort -u
}
#####################################################################
_CA_SED__VARIABLE_NAME() {
sed 's/^export //; s/=.*//; s/__RESTORE__//g'
}

74
zsh/env-setup.zsh Normal file
View File

@ -0,0 +1,74 @@
_CA__INTERACTIVE_ENV_SETUP() {
local PROJECT_PATH="$1"
local NO_ENV="$PROJECT_PATH/$_CA__NO_ENV_SENTINEL"
printf 'set up a virtual environment now? [(Y)es / (n)o / n(e)ver] '
_CA_READ yn
case $yn in
e ) touch $NO_ENV; return 1 ;;
n ) return 1 ;;
esac
local ENV_VERSION=$(_CA__SELECT_VIRTUAL_ENV)
[ ! $ENV_VERSION ] && return 1
_CA__INIT_VIRTUAL_ENV $PROJECT_PATH $ENV_VERSION
}
#####################################################################
_CA__SELECT_VIRTUAL_ENV() {
local VERSION=$(_CA__GET_VIRTUALENVS | _CA_FZF 'select an environment')
[[ $VERSION =~ node ]] && {
FIRST_PICK=$VERSION
VERSION=$(nodeenv --list 2>&1 \
| _CA_MULTILINE \
| sort --reverse --human-numeric-sort \
| _CA_FZF 'which node version?')
[[ $VERSION == $FIRST_PICK ]] && return
}
echo $VERSION
}
#####################################################################
_CA__INIT_VIRTUAL_ENV() {
local PROJECT_PATH="$1"
local ENV_VERSION="$2"
local ENV_PATH="$PROJECT_PATH/$_CA__VIRTUAL_ENV_NAME"
[[ $ENV_VERSION =~ ^[0-9] ]]\
&& _CA__INIT_NODE_ENV $ENV_PATH $ENV_VERSION \
|| _CA__INIT_VIRTUALENV $ENV_PATH $ENV_VERSION \
;
}
_CA__INIT_NODE_ENV() {
local ENV_PATH="$1"
local ENV_VERSION="$2"
echo "setting up node env ($ENV_VERSION)"
nodeenv --node=$ENV_VERSION $ENV_PATH
echo "done"
}
_CA__INIT_VIRTUALENV() {
local ENV_PATH="$1"
local ENV_VERSION="$2"
echo "setting up virtualenv ($ENV_VERSION)"
virtualenv --python=$ENV_VERSION $ENV_PATH
echo "done"
}
#####################################################################
_CA__GET_VIRTUALENVS() {
whence -pm '*' | grep python | grep -v -- '-config$\|m$'
which node 2>/dev/null
}

52
zsh/git.zsh Normal file
View File

@ -0,0 +1,52 @@
_CA__GIT_CLONE() {
local PROJECT_PATH="$1"
local REMOTE_TARGET="$2"
local SOURCE_DIR="$PROJECT_PATH/$CA__SOURCE_DIR"
[ -d $PROJECT_PATH ] && {
echo "project '$PROJECT_NAME' already exists in '$(basename $BASE_DIR)'"
return 1
}
echo "trying to clone '$REMOTE_TARGET' to '$PROJECT_PATH'"
git clone "$REMOTE_TARGET" "$SOURCE_DIR" >/dev/null 2>&1 || {
_CA_ERROR "failed to clone '$REMOTE_TARGET'"
printf "is this a new project? [y/N]"
_CA_READ yn
[[ $yn =~ ^[yY] ]] && {
_CA__GIT_INIT $PROJECT_PATH $REMOTE_TARGET || return 1
} || {
printf "cleaning up code-activator artifacts..."
rmdir $PROJECT_PATH
echo 'done'
}
}
}
_CA__GIT_INIT() {
local PROJECT_PATH="$1"
local REMOTE_TARGET="$2"
local SOURCE_DIR="$PROJECT_PATH/$CA__SOURCE_DIR"
[ -d $PROJECT_PATH ] && {
echo "project '$PROJECT_NAME' already exists in '$(basename $BASE_DIR)'"
return 1
}
printf "initializing '$(basename $PROJECT_PATH)'..."
{
mkdir -p $SOURCE_DIR \
&& cd $SOURCE_DIR \
&& git init \
&& touch .gitignore \
&& git add .gitignore \
&& git commit -m '[INIT] repo initialized!' \
&& git remote add origin $REMOTE_TARGET \
;
} >/dev/null 2>&1 && echo 'success!' || {
echo 'failed to initialize repo; cleaning up'
[ ! -d $SOURCE_DIR/.git ] && rm -rf $PROJECT_PATH
return 1
}
}

View File

@ -1,37 +1,3 @@
#####################################################################
[ ! $_CA__SETTINGS_LOADED ] && source "${0:a:h}/settings.zsh"
#####################################################################
_CA__RESTORE_ENVIRONMENT() {
deactivate >/dev/null 2>&1
deactivate_node >/dev/null 2>&1
[ $_CA__RESTORE_PATH ] && export PATH="$_CA__RESTORE_PATH"
[[ ${#_CA__RESTORE_ENV[@]} -gt 0 ]] \
&& for var in $_CA__RESTORE_ENV; do unset $var; done
_CA__TMUX_RESTORE_WINDOW_NAME
unset _CA__RESTORE_PATH _CA__RESTORE_ENV
}
_CA__GET_FULL_PATH() {
local PROJECT="$1"
local PROJECT_ROOT_SHORT=$(dirname $PROJECT)
local PROJECT_NAME=$(basename $PROJECT)
local FULL_BASE_DIR=$(\
echo $CODE_ACTIVATOR__DIRS \
| _CA__SED_MULTILINE \
| grep "^.*/$PROJECT_ROOT_SHORT$" \
)
echo "$FULL_BASE_DIR/$PROJECT_NAME"
}
_CA__TMUX_WINDOW_RENAME() {
local PROJECT="$1"
@ -43,137 +9,3 @@ _CA__TMUX_RESTORE_WINDOW_NAME() {
[[ $TERM =~ ^tmux- ]] \
&& tmux set automatic-rename on
}
_CA__SELECT_BASE_DIR() {
local BASE_NAMES=()
for dir in $CODE_ACTIVATOR__DIRS
do
BASE_NAMES=($BASE_NAMES $(basename $dir))
done
echo $CODE_ACTIVATOR__DIRS | _CA__SED_MULTILINE \
| grep $(\
echo $BASE_NAMES \
| _CA__SED_MULTILINE \
| $_CA__FZF --prompt 'select base directory : ')
}
_CA__GET_REMOTE_TARGET() {
local REMOTE_TARGET=$(\
echo $CODE_ACTIVATOR__KNOWN_TARGETS \
| _CA__SED_MULTILINE \
| $_CA__FZF --print-query --prompt 'set a remote target : ' \
| tail -1 \
)
local FIRST_SELECTION="$REMOTE_TARGET"
echo $CODE_ACTIVATOR__KNOWN_TARGETS | grep -q "$REMOTE_TARGET" && {
REMOTE_TARGET="$REMOTE_TARGET$(echo | $_CA__FZF --print-query --prompt "$REMOTE_TARGET" | tail -1)"
[[ $REMOTE_TARGET == $FIRST_SELECTION ]] && return ''
}
echo $REMOTE_TARGET | grep -q '\.git$' || REMOTE_TARGET="$REMOTE_TARGET.git"
echo $REMOTE_TARGET
}
_CA__GET_GIT_MAIN_BRANCH() {
{ git config --list | grep 'init.defaultbranch' | sed 's/.*=//' \
|| echo 'main'
} 2>/dev/null
}
_CA__GET_PROJECT_NAME() {
local REMOTE_TARGET="$1"
local DEFAULT_NAME=$(basename $REMOTE_TARGET | sed 's/\.git$//')
echo $DEFAULT_NAME | $_CA__FZF --print-query --prompt 'set local project name : ' | tail -1
}
_CA__INTERACTIVE_ENV_SETUP() {
local PROJECT_PATH="$1"
local NO_ENV="$PROJECT_PATH/$_CA__NO_ENV_SENTINEL"
printf 'set up a virtual environment now? [(Y)es / (n)o / n(e)ver] '
_CA__READ_K yn
case $yn in
e ) touch $NO_ENV; return 1 ;;
n ) return 1 ;;
esac
local ENV_VERSION=$(_CA__SELECT_VIRTUAL_ENV)
[ ! $ENV_VERSION ] && return 1
_CA__INIT_VIRTUAL_ENV $PROJECT_PATH $ENV_VERSION
}
_CA__SELECT_VIRTUAL_ENV() {
local VERSION=$(\
echo "$(_CA__GET_PYTHON_IN_PATH)\n$(which node 2>/dev/null)" \
| $_CA__FZF --prompt 'select a virtual environment : ' \
)
[[ $VERSION =~ node$ ]] && {
FIRST_PICK=$VERSION
VERSION=$(\
nodeenv --list 2>&1 \
| _CA__SED_MULTILINE \
| $_CA__FZF --prompt 'select a node version : '\
)
[[ $VERSION == $FIRST_PICK ]] && return
}
echo $VERSION
}
_CA__GET_PYTHON_IN_PATH() {
whence -pm '*' | grep python | grep -v -- '-config$\|m$'
}
_CA__INIT_VIRTUAL_ENV() {
local PROJECT_PATH="$1"
local ENV_VERSION="$2"
local ENV_PATH="$PROJECT_PATH/$_CA__VIRTUAL_ENV_NAME"
[[ $ENV_VERSION =~ ^[0-9] ]]\
&& _CA__INIT_NODE_ENV $ENV_PATH $ENV_VERSION \
|| _CA__INIT_VIRTUALENV $ENV_PATH $ENV_VERSION \
;
}
_CA__INIT_NODE_ENV() {
local ENV_PATH="$1"
local ENV_VERSION="$2"
echo "setting up node env ($ENV_VERSION)"
nodeenv --node=$ENV_VERSION $ENV_PATH
echo "done"
}
_CA__INIT_VIRTUALENV() {
local ENV_PATH="$1"
local ENV_VERSION="$2"
echo "setting up virtualenv ($ENV_VERSION)"
virtualenv --python=$ENV_VERSION $ENV_PATH
echo "done"
}
_CA__INIT_CUSTOM_ENV() {
local PROJECT_PATH="$1"
local CUSTOM_ENV_TEMPLATE="$_CA__CUSTOM_ENV_TEMPLATE"
local CUSTOM_ENV="$PROJECT_PATH/$_CA__CUSTOM_ENV_NAME"
cp $CUSTOM_ENV_TEMPLATE $CUSTOM_ENV
}
_CA__SED_MULTILINE() { sed 's/\s\+/\n/g'; }
#####################################################################
export _CA__HELPERS_LOADED=1

0
zsh/init.zsh Normal file
View File

45
zsh/interactive.zsh Normal file
View File

@ -0,0 +1,45 @@
_CA__SELECT_BASE_DIR() {
local BASE_NAMES=()
for dir in $CA__DIRS; do BASE_NAMES+=$(basename $dir); done
BASE_NAMES=$(echo $BASE_NAMES | _CA_MULTILINE)
SELECTION=$(echo $BASE_NAMES | _CA_FZF 'select base directory')
[ $SELECTION ] && echo $CA__DIRS | _CA_MULTILINE | grep -- $SELECTION
}
#####################################################################
_CA__GET_REMOTE_TARGET() {
local REMOTE_TARGET=$(\
echo $CA__KNOWN_TARGETS \
| _CA_MULTILINE | _CA_FZF_PRINT 'set a remote target' \
)
local FIRST_SELECTION="$REMOTE_TARGET"
echo $CA__KNOWN_TARGETS | grep -q "$REMOTE_TARGET" && {
REMOTE_TARGET="$REMOTE_TARGET$(_CA__GET_REPOS $REMOTE_TARGET )"
[[ $REMOTE_TARGET == $FIRST_SELECTION ]] && return ''
}
echo $REMOTE_TARGET | grep -q '\.git$' || REMOTE_TARGET="$REMOTE_TARGET.git"
echo $REMOTE_TARGET
}
_CA__GET_REPOS() {
local REMOTE_TARGET="$1"
# @TODO: github / bitbucket API integration
echo | _NOSEP=1 _CA_FZF_PRINT "$REMOTE_TARGET"
}
#####################################################################
_CA__GET_PROJECT_NAME() {
local REMOTE_TARGET="$1"
local DEFAULT_NAME=$(basename $REMOTE_TARGET | sed 's/\.git$//')
echo $DEFAULT_NAME | _CA_FZF_PRINT 'set local project name'
}

View File

@ -1,36 +0,0 @@
#####################################################################
[[ ${#CODE_ACTIVATOR__DIRS[@]} -eq 0 ]] && export CODE_ACTIVATOR__DIRS=("$HOME/Code")
export CODE_ACTIVATOR__KNOWN_TARGETS=(
$CODE_ACTIVATOR__KNOWN_TARGETS
'https://github.com/'
'https://bitbucket.org/'
'git@github.com:'
'git@bitbucket.org:'
)
[ ! $CODE_ACTIVATOR__SHORTCUT ] && export CODE_ACTIVATOR__SHORTCUT=''
[ ! $CODE_ACTIVATOR__ALIAS ] && export CODE_ACTIVATOR__ALIAS='lkj'
[ ! $CODE_ACTIVATOR__DISABLE_SHORTCUT ] && export CODE_ACTIVATOR__DISABLE_SHORTCUT=0
[ ! $CODE_ACTIVATOR__DISABLE_ALIAS ] && export CODE_ACTIVATOR__DISABLE_ALIAS=0
#####################################################################
export _CA__SOURCE_DIR_NAME='code'
export _CA__VIRTUAL_ENV_NAME='env'
export _CA__CUSTOM_ENV_NAME='custom-env'
export _CA__NO_ENV_SENTINEL='no-env'
export _CA__CUSTOM_ENV_TEMPLATE="${0:a:h}/custom-env-template.zsh"
#####################################################################
_CA__FZF=(fzf -i --height=50% --layout=reverse)
_CA__READ_K() { read -k $1; echo; }
#####################################################################
export _CA__SETTINGS_LOADED=1