Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
andrewscwei committed Jul 8, 2024
0 parents commit 4e7459c
Show file tree
Hide file tree
Showing 9 changed files with 964 additions and 0 deletions.
8 changes: 8 additions & 0 deletions .commitlintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
{
"rules": {
"subject-case": [
2,
"never"
]
}
}
53 changes: 53 additions & 0 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
name: Release
on:
push:
branches: [master]
permissions:
contents: write
jobs:
release:
name: Release
runs-on: ubuntu-latest
env:
GIT_AUTHOR_NAME: github-actions[bot]
GIT_AUTHOR_EMAIL: 41898282+github-actions[bot]@users.noreply.github.com
GIT_COMMITTER_NAME: github-actions[bot]
GIT_COMMITTER_EMAIL: 41898282+github-actions[bot]@users.noreply.github.com
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Node
uses: actions/setup-node@v4
with:
node-version: 21
- name: Release semantic version
run: npx semantic-release
- name: Release major version
run: |
VERSION="$(git tag --points-at ${{ github.sha }})"
if [ -z $VERSION ]; then
echo "No major version to publish" >> $GITHUB_STEP_SUMMARY
else
MAJOR_VERSION="$(cut -d '.' -f 1 <<< "$VERSION")"
git config user.name "${GIT_AUTHOR_NAME}"
git config user.email "${GIT_AUTHOR_EMAIL}"
git tag -fa ${MAJOR_VERSION} -m "Map ${MAJOR_VERSION} to ${VERSION}"
git push origin ${MAJOR_VERSION} --force
echo "Successfully published semantic version \`$VERSION\` and major version \`$MAJOR_VERSION\`" >> $GITHUB_STEP_SUMMARY
fi
notify:
needs: [release]
name: Notify
if: always()
runs-on: ubuntu-latest
steps:
- uses: andrewscwei/telegram-action@v1
with:
success: ${{ needs.release.result == 'success' }}
cancelled: ${{ needs.release.result == 'cancelled' }}
bot-token: ${{ secrets.TELEGRAM_DEVOPS_BOT_TOKEN }}
chat-id: ${{ secrets.TELEGRAM_DEVOPS_CHAT_ID }}
27 changes: 27 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# OS generated files
Thumbs.db
ehthumbs.db
Desktop.ini
.DS_Store
.AppleDouble
.LSOverride
Icon\r
*~

# Keys
*.pem
*.crt
*.key

# Temporary files
.tmp/

# Cache files
.cache/

# Secrets
*.secret

# mu resources
registry
registry-cache
17 changes: 17 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
default_stages: [pre-commit]
default_install_hook_types: [pre-commit, pre-push, commit-msg]
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.0.1
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-added-large-files
- repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook
rev: v9.16.0
hooks:
- id: commitlint
name: Lint commit message
stages: [commit-msg]
additional_dependencies:
- "@commitlint/config-conventional"
35 changes: 35 additions & 0 deletions .releaserc
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
{
"branches": [
"master"
],
"plugins": [
"@semantic-release/commit-analyzer",
"@semantic-release/release-notes-generator",
"@semantic-release/changelog",
[
"@semantic-release/exec",
{
"prepareCmd": "sed -i 's/VERSION=\"[^\"]*\"/VERSION=\"'${nextRelease.version}'\"/' install.sh && sed -i 's/VERSION=\"[^\"]*\"/VERSION=\"'${nextRelease.version}'\"/' mu.sh && sed -i 's|\\(https://raw.githubusercontent.com/andrewscwei/mu/v\\)[^\"/]*\\(/install.sh\\)|\\1'${nextRelease.version}'\\2|' README.md"
}
],
[
"@semantic-release/git",
{
"assets": [
"install.sh",
"mu.sh",
"CHANGELOG.md",
"README.md"
],
"message": "chore: Release `v${nextRelease.version}` [skip ci]"
}
],
[
"@semantic-release/github",
{
"successComment": false,
"failComment": false
}
]
]
}
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2024 Andrew Wei

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
62 changes: 62 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
# mu

> A productivity-focused CLI for switching between and interacting with local projects
`mu` is a CLI that allows you to switch your working directory to another local directory quickly. It also provides shortcuts for performing common operational tasks if that directory is a Git repo.

## TL;DR

First you need to teach `mu` where to look for your projects:

1. From Terminal, `cd` to the directory of a repo.
2. Run `mu add <project_key>` to add the current directory to the `mu` registry, where `<project_key>` is the key you wish to use to name this project.

From now on you can just run `mu cd <project_key>` to navigate to that project directly from Terminal. Better yet, you can run `mu project <project_key>` (or `mu p <project_key>` for short) to immediate open it with your default text editor (`mu` scans for Xcode project files and Android Studio projects first then falls back to VSCode/Sublime/Atom/TextMate respectively, depending on which editor is installed in your system).

## Usage

Install mu via cURL:

```sh
$ curl -o- https://raw.githubusercontent.com/andrewscwei/mu/v1.0.0/install.sh | bash
```

## Commands

```sh
Usage: mu <command> or mu <command> -h for more info

where <command> is one of:
add - Maps the current working directory to a project key (alias: a)
cd - Changes the current working directory to the working directory of a project
clean - Cleans the registry by reconciling invalid entries
edit - Edits the registry file directly in the default text editor (USE WITH CAUTION)
help - Provides access to additional info regarding specific commands (alias: h)
list - Lists all current projects in the registry (aliases: ls, l)
project - Opens a project in intended IDE (alias: p)
remove - Removes a project from the registry (aliases: rm, r)

GitHub:
gist - Downloads all files from a gist to the working directory
```

### `mu add <project_key>`
Maps the current working directory to a project key. If you don't specify a project key, the name of the current working directory will be used.

### `mu cd <project_key_or_index>`
Changes the working directory to the working directory of a `mu` project.

### `mu list`
Lists all current projects managed by `mu`

### `mu project <project_key_or_index>`
Opens a `mu` project in designated IDE (supports Xcode/Sublime in respective priority).

### `mu remove <project_key_or_index>`
Removes a `mu` project from the `mu` registry. If you don't specify a project key or index, the name of the current working directory will be used.

> Whenever you run a command that expects a project key or index, you can optionally leave the key or index blank. The command infers it from the last used key. You can run `mu cache` to see what the last interacted project is.
> Whenever you run a command that expects a project key or index, you can use `.` to refer to the current working directory (`pwd`).
> Most commands have 1-letter short notations. For example, instead of doing `mu project` you can do `mu p`.
122 changes: 122 additions & 0 deletions install.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
#!/usr/bin/env bash

{ # This ensures the entire script is downloaded

# Config.
VERSION="1.0.0"
SOURCE=https://raw.githubusercontent.com/andrewscwei/mu/v$VERSION/mu.sh

# Colors.
COLOR_PREFIX="\x1b["
COLOR_RESET=$COLOR_PREFIX"0m"
COLOR_BLACK=$COLOR_PREFIX"0;30m"
COLOR_RED=$COLOR_PREFIX"0;31m"
COLOR_GREEN=$COLOR_PREFIX"0;32m"
COLOR_ORANGE=$COLOR_PREFIX"0;33m"
COLOR_BLUE=$COLOR_PREFIX"0;34m"
COLOR_PURPLE=$COLOR_PREFIX"0;35m"
COLOR_CYAN=$COLOR_PREFIX"0;36m"
COLOR_LIGHT_GRAY=$COLOR_PREFIX"0;37m"

# Checks if a command is available.
#
# @param $1 Name of the command.
function cmd_exists() {
type "$1" > /dev/null 2>&1
}

# Gets the default install path. This can be overridden when calling the
# download script by passing the `MU_DIR` variable.
function install_dir() {
printf %s "${MU_DIR:-"$HOME/.mu"}"
}

# Installs mu as a script.
function install() {
local dest="$(install_dir)"

mkdir -p "$dest"

if [ -f "$dest/mu.sh" ]; then
echo -e "${COLOR_BLUE}mu: mu ${COLOR_ORANGE}is already installed in ${COLOR_CYAN}$dest${COLOR_ORANGE}, updating it instead...${COLOR_RESET}"
else
echo -e "${COLOR_BLUE}mu: ${COLOR_RESET}Downloading ${COLOR_BLUE}mu${COLOR_RESET} to ${COLOR_CYAN}$dest${COLOR_RESET}"
fi

# Download the script.
curl --compressed -q -s "$SOURCE" -o "$dest/mu.sh" || {
echo >&2 "${COLOR_BLUE}mu: ${COLOR_RED}Failed to download from ${COLOR_CYAN}$SOURCE${COLOR_RESET}"
return 1
}

# Make script executable.
chmod a+x "$dest/mu.sh" || {
echo >&2 "${COLOR_BLUE}mu: ${COLOR_RED}Failed to mark ${COLOR_CYAN}$dest/mu.sh${COLOR_RESET} as executable"
return 3
}
}

# Main process
function main() {
# Download and install the script.
if cmd_exists curl; then
install
else
echo >&2 "${COLOR_BLUE}mu: ${COLOR_RED}You need ${COLOR_CYAN}curl${COLOR_RED} to install ${COLOR_BLUE}mu${COLOR_RESET}"
exit 1
fi

# Edit Bash and ZSH profile files to set up mu.
local dest="$(install_dir)"
local bashprofile=""
local zshprofile=""
local sourcestr="\nalias mu='. ${dest}/mu.sh'\n"

if [ -f "$HOME/.bashrc" ]; then
bashprofile="$HOME/.bashrc"
elif [ -f "$HOME/.profile" ]; then
bahsprofile="$HOME/.profile"
elif [ -f "$HOME/.bash_profile" ]; then
bashprofile="$HOME/.bash_profile"
fi

if [ -f "$HOME/.zshrc" ]; then
zshprofile="$HOME/.zshrc"
fi

if [[ "$bashprofile" == "" ]] && [[ "$zshprofile" == "" ]]; then
echo -e "${COLOR_BLUE}mu: ${COLOR_RESET}Bash profile not found, tried ${COLOR_CYAN}~/.bashrc${COLOR_RESET}, ${COLOR_CYAN}~/.zshrc${COLOR_RESET}, ${COLOR_CYAN}~/.profile${COLOR_RESET} and ${COLOR_CYAN}~/.bash_profile${COLOR_RESET}"
echo -e " Create one of them and run this script again"
echo -e " OR"
echo -e " Append the following lines to the correct file yourself:"
echo -e " ${COLOR_CYAN}${sourcestr}${COLOR_RESET}"
exit 1
fi

if [[ "$bashprofile" != "" ]]; then
if ! command grep -qc '/mu.sh' "$bashprofile"; then
echo -e "${COLOR_BLUE}mu: ${COLOR_RESET}Appending ${COLOR_BLUE}mu${COLOR_RESET} source string to ${COLOR_CYAN}$bashprofile${COLOR_RESET}"
command printf "${sourcestr}" >> "$bashprofile"
else
echo -e "${COLOR_BLUE}mu: mu ${COLOR_RESET}source string is already in ${COLOR_CYAN}$bashprofile${COLOR_RESET}"
fi
fi

if [[ "$zshprofile" != "" ]]; then
if ! command grep -qc '/mu.sh' "$zshprofile"; then
echo -e "${COLOR_BLUE}mu: ${COLOR_RESET}Appending ${COLOR_BLUE}mu${COLOR_RESET} source string to ${COLOR_CYAN}$zshprofile${COLOR_RESET}"
command printf "${sourcestr}" >> "$zshprofile"
else
echo -e "${COLOR_BLUE}mu: mu ${COLOR_RESET}source string is already in ${COLOR_CYAN}$zshprofile${COLOR_RESET}"
fi
fi

# Source mu
\. "$dest/mu.sh"

echo -e "${COLOR_BLUE}mu: ${COLOR_GREEN}Installation complete. Close and reopen your terminal to start using ${COLOR_BLUE}mu${COLOR_RESET}"
}

main

} # This ensures the entire script is downloaded
Loading

0 comments on commit 4e7459c

Please sign in to comment.