Skip to content

Instantly share code, notes, and snippets.

@ewen-lbh
Created January 9, 2021 23:38
Show Gist options
  • Save ewen-lbh/3d530c029fcf3d1fe0a64ed50e17e5df to your computer and use it in GitHub Desktop.
Save ewen-lbh/3d530c029fcf3d1fe0a64ed50e17e5df to your computer and use it in GitHub Desktop.
function startproject --description "Start a project."
argparse --name="startproject" \
'd/description=' \
'h/help' \
'p/path=' \
'l/language=' \
'o/owner=' \
'k/kind=!startproject__validate_flag__kind' \
'D/debug' \
-- $argv
if test $status != 0
return
end
if not which gh jq git 1>/dev/null
echo "Please install the following required software:"
echo "· gh https://cli.github.com/"
echo "· jq https://stedolan.github.io/jq/"
echo "· git https://git-scm.org"
echo ""
echo "Additionnaly, to manage changelogs, it is recommended to use:"
echo "· chachacha https://github.com/aogier/chachacha"
return 1
end
set --local wd (pwd)
set --local name "$argv[1]"
set --local today (date +%Y-%m-%d)
set --local is_wsl (cat /proc/version | grep "Microsoft@Microsoft.com")
set --local tags ""
set --local technologies ""
set --local description "$_flag_description"
set --local language "$_flag_language"
set --local path "$_flag_path"
set --local owner "$_flag_owner"
if test -z $owner
set owner ewen-lbh
end
set --local kind $_flag_kind
if test -z $kind
set kind bin
end
echo "-----Running with-------"
echo "name: $name"
echo "description: $description"
echo "language: $language"
echo "path: $path"
echo "owner: $owner"
echo "kind: $kind"
echo "------------------------"
echo ""
if set -q _flag_debug
return
end
if test -z "$name"
echo "Provide a name as the first argument"
return 1
end
if test -z "$path"
set path $name
end
if test -e "$HOME/projects/$path"
echo "You already have a project at ~/projects/$path"
return 1
end
cd ~/projects
# Just in case a directory named $name already exists
set --local tempname $name.startproject-temp-move-(random)
if test -e $name
echo "WARN: ~/projects/$name already exists. Do not interrupt the command."
echo " If you must, you'll find ~/projects/$name at ~/projects/$tempname"
mv $name $tempname
or return $status
end
# Github
# Do this first cuz it can't initialize in the current directory, it must create one.
# Test if the repo already exists.
if gh api repos/$owner/$name 1>/dev/null
# Here the repo already exists. Ask if you want to abort or add it as a remote to the new project.
echo "The github repository https://github.com/$owner/$name already exists. What to do?"
echo " 1. Abort"
echo " 2. Create a folder and add the repo as a remote. This requires having jq installed."
read --prompt 'echo "[1|2] "' answer
if test $answer = 2
mkdir $path
cd $path
set remote_url (gh api repos/$owner/$name | jq .clone_url -r)
set branches (gh api repos/$owner/$name/branches | jq ".[].name" -r)
# Decide which branch to use: main or master or the first one
if test -z $branches
set --local default_init_branch_git (git config --global init.defaultBranch; or echo master)
echo "Remote has no branches, defaulting to $default_init_branch_git"
set upstream_branch $default_init_branch_git
else if echo $branches | grep main
set upstream_branch main
else if echo $branches | grep master
set upstream_branch master
else
set upstream_branch (echo $branches | head -n 1)
echo "WARN: Neither main nor master branches exists on remote"
if test -z $upstream_branch
echo "Could not get the upstream branch from the following branches:" (echo $branches | string join ', ')
end
end
git init
git remote add origin $remote_url
else
echo "Aborting."
return
end
else
if test -n "$description"
gh repo create $name -y --public --description "$description"
else
gh repo create $name -y --public
end
# There's also no way to separate the repo's name from the created directory
if test $name != $path
mv $name $path
end
cd $path
end
# Some languages have code generation utilities
# This also sets tags
set --local target generated-(random)
if test $kind = "lib"
set tags "library"
else
set tags "program"
end
set technologies $language
switch $language
case rust
if not which cargo 1>/dev/null
echo "Install cargo to use --language=rust"
return 1
end
set --local cargo_kind $kind
if test $cargo_kind = "app"
set cargo_kind "bin"
end
cargo new --$cargo_kind --name $name $target --vcs git
or return $status
case python
if not which poetry 1>/dev/null
echo "Install poetry to use --language=python"
return 1
end
poetry new --name $name $target
or return $status
case svelte
set tags "web, app"
if not which degit 1>/dev/null
echo "Install degit to use --language=svelte"
return 1
end
degit sveltejs/template $name
or return $status
mv $name $target
if test -e $tempname
mv $tempname $name
end
case crystal
if not which crystal 1>/dev/null
echo "Install crystal to use --language=crystal"
return 1
end
crystal init $kind $name "$target"
case ruby
if not which bundle 1>/dev/null
echo "Install bundle to use --language=ruby"
return 1
end
if test $kind = "app"
bundle gem $target --bin
else
bundle gem $target
end
case rails
set technologies "ruby-on-rails"
if not which rails 1>/dev/null
echo "Install rails to use --language=rails"
return 1
end
set --local args ""
if test -n $is_wsl
set args "$args --skip-spring --skip-listen"
# See https://guides.rubyonrails.org/getting_started.html#creating-a-new-rails-project
end
set target $name
rails new $target $args
case go
echo "package $name" > $name.go
go mod init github.com/$owner/$name
case '*'
set tags ""
mkdir $target
end
# Some utils init git repositories, don't want to override gh's .git
if test -e $target/.git
rm -rf $target/.git
end
# Pull all files from $target to the current directory
if find . -maxdepth 1 -name "*" 2>/dev/null | grep -q .
mv $target/* .
end
if find . -maxdepth 1 -name ".*" 2>/dev/null | grep -q .
mv $target/.* .
end
if test -e $target
rmdir $target
end
or return 1
# Install deps
# NB: this makes it clear which programming languages
# have one standard package manager everyone aggrees on
# and which are just a mess haha
if test -e package.json
set --local pm npm
if which pnpm 1>/dev/null
set pm pnpm
else if which yarn 1>/dev/null
set pm yarn
else if not which npm 1>/dev/null
echo "Install pnpm, yarn or npm"
return 1
end
$pm install
else if test -e Cargo.toml
cargo build
else if test -e pyproject.toml
set --local pm pip
if which poetry 1>/dev/null
set pm poetry
else if which pipenv 1>/dev/null
set pm pipenv
else if not which npm 1>/dev/null
echo "Install poetry, pip or pipenv"
return 1
end
$pm install
else if test -e shard.yml
shards install
else if test -e go.mod
go install
end
# Changelog
if not which chachacha 1>/dev/null
echo "WARN: chachacha is not installed, not initializing CHANGELOG.md"
else
chachacha init
end
# README
if not test -e README.md
echo "# $name" > README.md
if test -n "$description"
echo "$description" >> README.md
end
end
# portfoliodb
mkdir .portfoliodb
cd .portfoliodb
touch description.md
echo "---" >> description.md
echo "started: $today" >> description.md
echo "tags: [$tags]" >> description.md
echo "made with: [$technologies]" >> description.md
echo "---" >> description.md
echo "" >> description.md
echo "# $name" >> description.md
if test -n "$description"
echo "" >> description.md
echo ":: en" >> description.md
echo "" >> description.md
echo "$description" >> description.md
end
cd ..
# Gitignore
if test -n $language -a ! -e .gitignore
create-gitignore $language 1>/dev/null
end
git add .
and git commit -m "🎉 Initial commit"
and git branch -M $upstream_branch
and git push -u origin $upstream_branch &
code-insiders .
# Move back the old $name folder (see beginning of script)
cd ~/projects
if test -e $tempname -a ! -e $name
mv $tempname $name
end
cd "$wd"
end
function startproject__validate_flag__kind --no-scope-shadowing
set alloweds "lib app"
echo $alloweds | grep $_flag_value 1>/dev/null
if test $status != 0
echo "Illegal value for --kind: $_flag_value"
echo "Allowed values are: "
for value in (echo $alloweds | string split ' ')
echo "· $value"
end
return 1
end
return 0
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment