Merge remote-tracking branch 'origin/master' into refactor_of_git_status

This commit is contained in:
Willa Drengwitz
2018-08-31 13:24:24 -04:00
27 changed files with 714 additions and 394 deletions

View File

@@ -1,3 +1,16 @@
script: ./run_tests.sh
os:
- linux
- osx
env:
- TEST_SHELLS=bash
- TEST_SHELLS=zsh
install:
- ./test/support/travisci_deps.sh
before_script:
- sudo apt-get install zsh
- echo -e "test_repo_11\ntest_repo_1" | sort
script:
- ./run_tests.sh

View File

@@ -1,41 +1,81 @@
# SCM Breeze [![TravisCI](https://secure.travis-ci.org/ndbroadbent/scm_breeze.png?branch=master)](http://travis-ci.org/ndbroadbent/scm_breeze)
### Streamline your SCM workflow.
**SCM Breeze** is a set of shell scripts (for `bash` and `zsh`) that enhance your interaction with git. It integrates with your shell to give you numbered file shortcuts,
a repository index with tab completion, and many other useful features.
<hr/>
## Demo video
<center><a href="http://www.youtube.com/watch?v=iKdp6uBfrvc" target="_blank"><img src="http://i.imgur.com/l7aGG.png"></a></center>
<hr/>
## File Shortcuts
SCM Breeze makes it really easy to work with changed files, and groups of changed files.
Whenever you view your SCM status, each modified path is stored in a numbered environment variable.
You can configure the variable prefix, which is 'e' by default.
<img src="https://user-images.githubusercontent.com/139536/30827652-08e9b684-a265-11e7-95fb-50cbd2fb7c0d.png" width="200" height="200">
### Git Status Shortcuts:
# SCM Breeze [![TravisCI](https://secure.travis-ci.org/scmbreeze/scm_breeze.png?branch=master)](http://travis-ci.org/scmbreeze/scm_breeze)
> Streamline your SCM workflow.
**SCM Breeze** is a set of shell scripts (for `bash` and `zsh`) that enhance
your interaction with git. It integrates with your shell to give you numbered
file shortcuts, a repository index with tab completion, and many other useful
features.
![SCM Breeze Example Gif](http://i.imgur.com/3fD8cpo.gif)
- [Installation](#installation)
- [Usage](#usage)
- [File Shortcuts](#file-shortcuts)
- [Keyboard bindings](#keyboard-bindings)
- [Repository Index](#repository-index)
- [Linking External Project Design Directories](#linking-external-project-design-directories)
- [Configuration](#configuration)
- [Updating](#updating)
- [Uninstalling](#uninstalling)
- [Notes about Tab Completion for Aliases](#notes-about-tab-completion-for-aliases)
- [Contributing](#contributing)
## Installation
```bash
git clone git://github.com/scmbreeze/scm_breeze.git ~/.scm_breeze
~/.scm_breeze/install.sh
source ~/.bashrc # or source ~/.zshrc
```
The install script creates required default configs and adds the following line
to your `.bashrc` or `.zshrc`:
`[ -s "$HOME/.scm_breeze/scm_breeze.sh" ] && source "$HOME/.scm_breeze/scm_breeze.sh"`
**Note:** SCM Breeze performs much faster if you have ruby installed.
## Usage
<center><a href="http://www.youtube.com/watch?v=iKdp6uBfrvc"
target="_blank"><img src="http://i.imgur.com/l7aGG.png"></a></center>
### File Shortcuts
SCM Breeze makes it really easy to work with changed files, and groups of
changed files. Whenever you view your SCM status, each modified path is stored
in a numbered environment variable. You can configure the variable prefix,
which is 'e' by default.
#### Git Status Shortcuts:
<div class="centered">
<img src="http://madebynathan.com/images/posts/2011/10/status_with_shortcuts-resized-post.png" width="590" alt="Git Status With Shortcuts" />
</div>
<br/>
### 'ls' shortcuts:
#### 'ls' shortcuts:
<div class="centered">
<img src="http://i.imgur.com/72GE1.png" alt="Ls With Shortcuts" />
</div>
<br/>
These numbers (or ranges of numbers) can be used with any SCM or system command.
These numbers (or ranges of numbers) can be used with any SCM or system
command.
For example, if `ga` was your alias for `git add`, instead of typing something like:
For example, if `ga` was your alias for `git add`, instead of typing something
like:
```bash
$ ga assets/git_breeze/config* assets/git_breeze/install.sh
@@ -47,8 +87,8 @@ You can type this instead:
$ ga $e2 $e3 $e11
```
But SCM Breeze aliases `ga` to the `git_add_shortcuts` function,
which is smart enough to expand integers and ranges, so all you need to type is:
But SCM Breeze aliases `ga` to the `git_add_shortcuts` function, which is smart
enough to expand integers and ranges, so all you need to type is:
```bash
$ ga 2 3 11
@@ -60,8 +100,8 @@ And if you want to add all unstaged changes (files 1 to 10):
$ ga 1-10
```
(Note that `ga` will also remove deleted files, unlike the standard `git add` command.
This behaviour can be turned off if you don't like it.)
(Note that `ga` will also remove deleted files, unlike the standard `git add`
command. This behaviour can be turned off if you don't like it.)
You can also diff, reset or checkout a file by typing:
@@ -73,8 +113,8 @@ $ gco 5
```
You can use these shortcuts with system commands by passing your command through `exec_scmb_expand_args`
(default alias is 'ge'):
You can use these shortcuts with system commands by passing your command
through `exec_scmb_expand_args` (default alias is `ge`):
```bash
@@ -88,19 +128,21 @@ $ ge echo 1-3
```
### Other shortcuts
#### Other shortcuts
SCM Breeze adds a number of aliases to your shell. Use `list_aliases` to view all the aliases and their corresponding commands.
You can filter aliases by adding a search string: `list_aliases git log`
SCM Breeze adds a number of aliases to your shell. Use `list_aliases` to view
all the aliases and their corresponding commands. You can filter aliases by
adding a search string: `list_aliases git log`
There's also a `git_aliases` command, which just shows aliases for `git` commands. You can also pass in additional filters, e.g. `git_aliases log`.
There's also a `git_aliases` command, which just shows aliases for `git`
commands. You can also pass in additional filters, e.g. `git_aliases log`.
## Keyboard bindings
### Keyboard bindings
Some of my most common git commands are `git add` and `git commit`, so I wanted these
to be as streamlined as possible. One way of speeding up commonly used commands is by binding them to
keyboard shortcuts.
Some of my most common git commands are `git add` and `git commit`, so I wanted
these to be as streamlined as possible. One way of speeding up commonly used
commands is by binding them to keyboard shortcuts.
Here are the default key bindings:
@@ -108,14 +150,13 @@ Here are the default key bindings:
* `CTRL`+`x` `SPACE` => `git_commit_all` - commit everything
The commit shortcuts use the `git_commit_prompt` function, which gives a simple prompt like this:
The commit shortcuts use the `git_commit_prompt` function, which gives a simple
prompt like this:
<div class="centered">
<img src="http://madebynathan.com/images/posts/2011/10/git_commit_all-resized-post.png" alt="Git Commit All" />
</div>
<br/>
(When using bash, this commit prompt gives you access to your bash history via the arrow keys.)
<br/>
<div class="centered"> <img
src="http://madebynathan.com/images/posts/2011/10/git_commit_all-resized-post.png"
alt="Git Commit All" /> </div> <br/> (When using bash, this commit prompt gives
you access to your bash history via the arrow keys.) <br/>
And if you really want to speed up your workflow, you can type this:
@@ -131,23 +172,26 @@ This sends the `HOME` key, followed by `git_add_and_commit`:
<br/>
## Repository Index
### Repository Index
The second feature is a repository index for all of your projects and submodules.
This gives you super-fast switching between your project directories, with tab completion,
and it can even tab-complete down to project subdirectories.
This means that you can keep your projects organized in subfolders,
but switch between them as easily as if they were all in one folder.
The second feature is a repository index for all of your projects and
submodules. This gives you super-fast switching between your project
directories, with tab completion, and it can even tab-complete down to project
subdirectories. This means that you can keep your projects organized in
subfolders, but switch between them as easily as if they were all in one
folder.
It's similar to [autojump](https://github.com/joelthelion/autojump), but it doesn't need to 'learn' anything,
and it can do SCM-specific stuff like:
It's similar to [autojump](https://github.com/joelthelion/autojump), but it
doesn't need to 'learn' anything, and it can do SCM-specific stuff like:
* Running a command for all of your repos (useful if you ever need to update a lot of remote URLs)
* Running a command for all of your repos (useful if you ever need to update a
lot of remote URLs)
* Update all of your repositories via a cron task
The default alias for `git_index` is 'c', which might stand for 'code'
You will first need to configure your repository directory, and then build the index:
You will first need to configure your repository directory, and then build the
index:
```bash
$ c --rebuild
@@ -155,10 +199,12 @@ $ c --rebuild
# => ===== Indexed 64 repos in /home/ndbroadbent/code/.git_index
```
Then you'll be able to switch between your projects, or show the list of indexed repos.
Then you'll be able to switch between your projects, or show the list of
indexed repos.
To switch to a project directory, you don't need to type the full project name. For example,
to switch to the `capistrano` project, you could type any of the following:
To switch to a project directory, you don't need to type the full project name.
For example, to switch to the `capistrano` project, you could type any of the
following:
```bash
$ c capistrano
@@ -177,19 +223,20 @@ $ c capistrano/lib/
# => cd ~/code/gems/capistrano/lib
```
Or if you want to go to a subdirectory within the `~/code` directory, prefix the first argument with a `/`:
Or if you want to go to a subdirectory within the `~/code` directory, prefix
the first argument with a `/`:
```bash
~ $ c /gems
~/code/gems $
```
## Linking External Project Design Directories
### Linking External Project Design Directories
When you're creating logos or icons for a project that uses `git`,
have you ever wondered where you should store those `.psd` or `.xcf` files?
Do you commit all of your raw design files, or does it put you off that any changes to those files
will bloat your repository?
When you're creating logos or icons for a project that uses `git`, have you
ever wondered where you should store those `.psd` or `.xcf` files? Do you
commit all of your raw design files, or does it put you off that any changes to
those files will bloat your repository?
Here were my goals when I set out to find a solution:
@@ -198,164 +245,168 @@ Here were my goals when I set out to find a solution:
* The design directory needed to be synchronized across all of my machines
The simplest way for me to synchronize files was via my Dropbox account.
However, if you work with a larger team, you could set up a shared design directory on one
of your servers and synchronize it with `rsync`.
However, if you work with a larger team, you could set up a shared design
directory on one of your servers and synchronize it with `rsync`.
### 1) Create and configure a root design directory
#### 1) Create and configure a root design directory
I created my root design directory at `~/Dropbox/Design`.
After you've created your root design directory, edit `~/.scmbrc` and set `root_design_dir`
to the directory you just created.
You can also configure the design directory that's created in each of your projects
(default: `design_assets`), as well as the subdirectories you would like to use.
The default base subdirectories are: Images, Backgrounds, Logos, Icons, Mockups, and Screenshots.
After you've created your root design directory, edit `~/.scmbrc` and set
`root_design_dir` to the directory you just created. You can also configure
the design directory that's created in each of your projects (default:
`design_assets`), as well as the subdirectories you would like to use. The
default base subdirectories are: Images, Backgrounds, Logos, Icons, Mockups,
and Screenshots.
After you have changed these settings, remember to run `source ~/.bashrc` or `source ~/.zshrc`.
After you have changed these settings, remember to run `source ~/.bashrc` or
`source ~/.zshrc`.
### 2) Initialize design directories for your projects
#### 2) Initialize design directories for your projects
To set up the design directories and symlinks, go to a project's directory and run:
To set up the design directories and symlinks, go to a project's directory and
run:
```bash
design init
```
If your root directory is `~/Dropbox/Design`, directories will be created at
`~/Dropbox/Design/projects/my_project/Backgrounds`, `~/Dropbox/Design/projects/my_project/Icons`, etc.
`~/Dropbox/Design/projects/my_project/Backgrounds`,
`~/Dropbox/Design/projects/my_project/Icons`, etc.
It will then symlink the project from your root design directory into your project's design directory,
so you end up with:
It will then symlink the project from your root design directory into your
project's design directory, so you end up with:
* `my_project/design_assets` -> `~/Dropbox/Design/projects/my_project`
It also adds this directory to `.git/info/exclude` so that git ignores it.
If you use the git repository index,
you can run the following batch command to set up these directories for all of your git repos at once:
If you use the git repository index, you can run the following batch command to
set up these directories for all of your git repos at once:
```bash
git_index --batch-cmd design init
```
If you want to remove any empty design directories, run:
```bash
design trim
```
And if you want to remove all of a project's design directories, even if they contain files:
And if you want to remove all of a project's design directories, even if they
contain files:
```bash
design rm
```
### 3) Link existing design directories into your projects
#### 3) Link existing design directories into your projects
If you've set up your design directories on one machine, you'll want them
to be synchronized across all of your other development machines.
If you've set up your design directories on one machine, you'll want them to be
synchronized across all of your other development machines.
Just run the following command on your other machines after you've configured the root design directory:
Just run the following command on your other machines after you've configured
the root design directory:
```bash
design link
```
This uses your git index to figure out where to create the symlinks.
If you don't use the git index, the same outcome could be achieved by running 'design init'
for each of the projects.
This uses your git index to figure out where to create the symlinks. If you
don't use the git index, the same outcome could be achieved by running 'design
init' for each of the projects.
## Configuration
## Contributing tools / scripts
SCM Breeze is configured via automatically installed `~/.*.scmbrc` files. To
change git configuration, edit `~/.git.scmbrc`.
If you have any awesome SCM scripts lurking in your `.bashrc` or `.zshrc`,
please feel free to send me a pull request.
It would be cool to make this project into an [oh-my-zsh](https://github.com/robbyrussell/oh-my-zsh) for SCMs.
Each feature is modular, so you are free to ignore the parts you don't want to
use. Just comment out the relevant line in `~/.scm_breeze/scm_breeze.sh`.
**Note:** After changing any settings, you will need to run `source ~/.bashrc`
(or `source ~/.zshrc`)
I know we grow attached to the aliases we use every day, so I've made the alias
system completely customizable. You have two options when it comes to aliases:
# Installation
### 1) Configure and use the provided SCM Breeze aliases
```bash
git clone git://github.com/ndbroadbent/scm_breeze.git ~/.scm_breeze
~/.scm_breeze/install.sh
source ~/.bashrc # or source ~/.zshrc
```
The install script just adds the following line to your `.bashrc` or `.zshrc`:
`[ -s "$HOME/.scm_breeze/scm_breeze.sh" ] && source "$HOME/.scm_breeze/scm_breeze.sh"`
Just tweak the aliases in `~/.git.scmbrc`. You can also change or remove any
keyboard shortcuts. These aliases also come with tab completion. For example,
you can type `gco <tab>` to tab complete your list of branches.
# Updating
### 2) Use your own aliases
Please run `update_scm_breeze` to fetch the latest code. This will update SCM Breeze from Github,
and will create or patch your `~/.*.scmbrc` config files if any new settings are added.
In your `git.scmbrc` config file, just set the `git_setup_aliases` option to
`no`. Your existing git aliases will then be used, and you will still be able
to use the numeric shortcuts feature. SCM Breeze creates a function to wrap
the 'git' command, which expands numeric arguments, and uses `hub` if
available.
# Uninstall
A few aliases will still be defined for the central SCM Breeze features, such
as `gs` for the extended `git status`, and `ga` for the `git add` function.
If you already have an alias like `alias gco="git checkout"`, you can now type
`gco 1` to checkout the first file in the output of SCM Breeze's `git status`.
## Notes about Tab Completion for Aliases
### Bash
If you use your own aliases, SCM Breeze will **not** set up bash tab completion
for your aliases. You will need to set that up yourself.
### Zsh
You just need to set the option: `setopt no_complete_aliases` (oh-my-zsh sets
this by default). Zsh will then expand aliases like `gb` to `git branch`, and
use the completion for that.
## Updating
Please run `update_scm_breeze` to fetch the latest code. This will update SCM
Breeze from Github, and will create or patch your `~/.*.scmbrc` config files if
any new settings are added.
## Uninstalling
```bash
~/.scm_breeze/uninstall.sh
```
The uninstall script removes the following line from your `.bashrc` or `.zshrc`:
The uninstall script removes the following line from your `.bashrc` or
`.zshrc`:
`[ -s "$HOME/.scm_breeze/scm_breeze.sh" ] && source "$HOME/.scm_breeze/scm_breeze.sh"`
# Configuration
SCM Breeze is configured via automatically installed `~/.*.scmbrc` files.
To change git configuration, edit `~/.git.scmbrc`.
## Contributing
Each feature is modular, so you are free to ignore the parts you don't want to use.
Just comment out the relevant line in `~/.scm_breeze/scm_breeze.sh`.
SCM Breeze lives on Github at
[`scmbreeze/scm_breeze`](https://github.com/scmbreeze/scm_breeze)
**Note:** After changing any settings, you will need to run `source ~/.bashrc` (or `source ~/.zshrc`)
If you have any awesome SCM scripts lurking in your `.bashrc` or `.zshrc`,
please feel free to send me a pull request. It would be cool to make this
project into an [oh-my-zsh](https://github.com/robbyrussell/oh-my-zsh) for
SCMs.
I know we grow attached to the aliases we use every day, so I've made the alias system completely customizable.
You have two options when it comes to aliases:
***Enjoy!***
### 1) Configure and use the provided SCM Breeze aliases
Just tweak the aliases in `~/.git.scmbrc`. You can also change or remove any keyboard shortcuts.
These aliases also come with tab completion. For example, you can type `gco <tab>` to tab complete your list of branches.
### 2) Use your own aliases
In your `git.scmbrc` config file, just set the `git_setup_aliases` option to `no`.
Your existing git aliases will then be used, and you will still be able to use the numeric shortcuts feature.
SCM Breeze creates a function to wrap the 'git' command, which expands numeric arguments, and uses `hub` if available.
A few aliases will still be defined for the central SCM Breeze features, such as `gs` for the extended `git status`,
and `ga` for the `git add` function.
If you already have an alias like `alias gco="git checkout"`,
you can now type `gco 1` to checkout the first file in the output of SCM Breeze's `git status`.
# Notes about Tab Completion for Aliases
### Bash
If you use your own aliases, SCM Breeze will **not** set up bash tab completion for your aliases.
You will need to set that up yourself.
### Zsh
You just need to set the option: `setopt no_complete_aliases` (oh-my-zsh sets this by default).
Zsh will then expand aliases like `gb` to `git branch`, and use the completion for that.
# Contributing
SCM Breeze lives on Github at [https://github.com/ndbroadbent/scm_breeze](https://github.com/ndbroadbent/scm_breeze)
Please feel free to fork and send pull requests, especially if you would like to build these features
for Mercurial, SVN, etc.
## Enjoy!
## Alternative Projects
1. https://github.com/shinriyo/breeze `fish` support
1. https://github.com/mroth/scmpuff static go binary

View File

@@ -34,13 +34,13 @@ git_alias="g"
# 1. 'SCM Breeze' functions
git_status_shortcuts_alias="gs"
git_add_shortcuts_alias="ga"
git_add_patch_alias="gap"
git_add_updated_alias="gau"
git_show_files_alias="gsf"
exec_scmb_expand_args_alias="ge"
git_show_files_alias="gsf"
git_commit_all_alias="gca"
git_grep_shortcuts_alias="gtrep"
# 2. Commands that handle paths (with shortcut args expanded)
git_checkout_alias="gco"
git_checkout_branch_alias="gcob"
git_checkout_branch_alias="gcb"
git_commit_alias="gc"
git_commit_verbose_alias="gcv"
git_reset_alias="grs"
@@ -48,6 +48,8 @@ git_reset_hard_alias="grsh"
git_rm_alias="grm"
git_blame_alias="gbl"
git_diff_alias="gd"
git_diff_no_whitespace_alias="gdnw"
git_diff_file_alias="gdf"
git_diff_word_alias="gdw"
git_diff_cached_alias="gdc"
git_difftool_alias="gdt"
@@ -57,6 +59,7 @@ git_fetch_alias="gf"
git_fetch_all_alias="gfa"
git_fetch_and_rebase_alias="gfr"
git_pull_alias="gpl"
git_pull_rebase_alias="gplr"
git_push_alias="gps"
git_push_force_alias="gpsf"
git_pull_then_push_alias="gpls"
@@ -65,7 +68,8 @@ git_status_short_alias="gss"
git_clean_alias="gce"
git_clean_force_alias="gcef"
git_add_all_alias="gaa"
git_commit_all_alias="gca"
git_add_patch_alias="gap"
git_add_updated_alias="gau"
git_commit_amend_alias="gcm"
git_commit_amend_no_msg_alias="gcmh"
git_commit_no_msg_alias="gch"
@@ -86,7 +90,7 @@ git_merge_only_fast_forward_alias="gmff"
git_cherry_pick_alias="gcp"
git_log_alias="gl"
git_log_all_alias="gla"
git_log_stat_alias="gls"
git_log_stat_alias="glst"
git_log_graph_alias="glg"
git_show_alias="gsh"
git_show_summary="gsm" # (gss taken by git status short)
@@ -95,6 +99,13 @@ git_stash_apply_alias="gasha"
git_stash_pop_alias="gashp"
git_stash_list_alias="gashl"
git_tag_alias="gt"
git_submodule_update_alias="gsu"
git_submodule_update_rec_alias="gsur"
git_top_level_alias="gtop"
git_whatchanged_alias="gwc"
git_apply_alias="gapp"
# Hub aliases (https://github.com/github/hub)
git_pull_request_alias="gpr"
# Git Keyboard Shortcuts
@@ -112,3 +123,5 @@ git_commit_all_with_ci_skip_keys="\C-xv" # CTRL+x, v (Appends [ci skip] to c
shell_command_wrapping_enabled="true"
# Here you can tweak the list of wrapped commands.
scmb_wrapped_shell_commands="vim emacs gedit cat rm cp mv ln cd"
# Add numbered shortcuts to output of ls -l, just like 'git status'
shell_ls_aliases_enabled="true"

View File

@@ -10,11 +10,19 @@ fi
# This loads SCM Breeze into the shell session.
exec_string="[ -s \"$HOME/.scm_breeze/scm_breeze.sh\" ] && source \"$HOME/.scm_breeze/scm_breeze.sh\""
# Add line to bashrc and zshrc if not already present.
for rc in bashrc zshrc; do
if [ -s "$HOME/.$rc" ] && ! grep -q "$exec_string" "$HOME/.$rc"; then
# Add line to bashrc, zshrc, and bash_profile if not already present.
added_to_profile=false
already_present=false
for rc in bashrc zshrc bash_profile; do
if [ -s "$HOME/.$rc" ]; then
if grep -q "$exec_string" "$HOME/.$rc"; then
printf "== Already installed in '~/.$rc'\n"
already_present=true
else
printf "\n$exec_string\n" >> "$HOME/.$rc"
printf "== Added SCM Breeze to '~/.$rc'\n"
added_to_profile=true
fi
fi
done
@@ -23,5 +31,12 @@ source "$scmbDir/lib/scm_breeze.sh"
# Create '~/.*.scmbrc' files from example files
_create_or_patch_scmbrc
echo "== Run 'source ~/.bashrc' or 'source ~/.zshrc' to load SCM Breeze into your current shell."
if [ "$added_to_profile" = true ] || [ "$already_present" = true ]; then
echo "== SCM Breeze Installed! Run 'source ~/.bashrc || source ~/.bash_profile' or 'source ~/.zshrc'"
echo " to load SCM Breeze into your current shell."
else
echo "== Error:"
echo " Found no profile to add SCM Breeze to."
echo " Add line to your shell profile and source it to install manually:"
printf " $exec_string\n"
fi

View File

View File

@@ -23,7 +23,7 @@
# Add ignore rule to .git/info/exclude if not already present
_design_add_git_exclude(){
local git_dir="$(cd $1 && readlink -m $(git rev-parse --git-dir))"
local git_dir="$(cd $1 && cd `git rev-parse --git-dir` && pwd -P)"
if [ -e "$git_dir/info/exclude" ] && ! $(grep -q "$project_design_dir" "$git_dir/info/exclude"); then
echo "$project_design_dir" >> "$git_dir/info/exclude"
fi
@@ -102,5 +102,6 @@ design() {
printf "Invalid command.\n\n"
design
fi
unset IFS
}

View File

@@ -21,12 +21,14 @@ export _git_cmd="$(\which git)"
# Wrap git with the 'hub' github wrapper, if installed (https://github.com/defunkt/hub)
if type hub > /dev/null 2>&1; then export _git_cmd="hub"; fi
# gh is now deprecated, and merged into the `hub` command line tool.
#if type gh > /dev/null 2>&1; then export _git_cmd="gh"; fi
# Create 'git' function that calls hub if defined, and expands all numeric arguments
function git(){
# Only expand args for git commands that deal with paths or branches
case $1 in
commit|blame|add|log|rebase|merge)
commit|blame|add|log|rebase|merge|difftool)
exec_scmb_expand_args "$_git_cmd" "$@";;
checkout|diff|rm|reset)
exec_scmb_expand_args --relative "$_git_cmd" "$@";;
@@ -37,7 +39,7 @@ function git(){
esac
}
_alias $git_alias='git'
_alias "$git_alias" "git"
# --------------------------------------------------------------------
@@ -64,91 +66,111 @@ _git
# Usage: __git_alias <alias> <command_prefix> <command>
__git_alias () {
if [ -n "$1" ]; then
local alias_str="$1"; local cmd_prefix="$2"; local cmd="$3"; local cmd_args="${4-}"
alias $alias_str="$cmd_prefix $cmd${cmd_args:+ }$cmd_args"
local alias_str cmd_prefix cmd cmd_args
alias_str="$1"; cmd_prefix="$2"; cmd="$3";
if [ $# -gt 2 ]; then
shift 3 2>/dev/null
cmd_args=$@
fi
alias $alias_str="$cmd_prefix $cmd${cmd_args:+ }${cmd_args[*]}"
if [ "$shell" = "bash" ]; then
__define_git_completion $alias_str $cmd
complete -o default -o nospace -F _git_"$alias_str"_shortcut $alias_str
__define_git_completion "$alias_str" "$cmd"
complete -o default -o nospace -F _git_"$alias_str"_shortcut "$alias_str"
fi
fi
}
# --------------------------------------------------------------------
# SCM Breeze functions
_alias $git_status_shortcuts_alias="git_status_shortcuts"
_alias $git_add_shortcuts_alias="git_add_shortcuts"
_alias $exec_scmb_expand_args_alias="exec_scmb_expand_args"
_alias $git_show_files_alias="git_show_affected_files"
_alias $git_commit_all_alias='git_commit_all'
_alias "$git_status_shortcuts_alias" 'git_status_shortcuts'
_alias "$git_add_shortcuts_alias" 'git_add_shortcuts'
_alias "$exec_scmb_expand_args_alias" 'exec_scmb_expand_args'
_alias "$git_show_files_alias" 'git_show_affected_files'
_alias "$git_commit_all_alias" 'git_commit_all'
_alias "$git_grep_shortcuts_alias" 'git_grep_shortcuts'
# Git Index alias
_alias $git_index_alias="git_index"
_alias "$git_index_alias" 'git_index'
# Only set up the following aliases if 'git_setup_aliases' is 'yes'
if [ "$git_setup_aliases" = "yes" ]; then
# Commands that deal with paths
__git_alias "$git_checkout_alias" "git" "checkout"
__git_alias "$git_commit_alias" "git" "commit"
__git_alias "$git_commit_verbose_alias" "git" "commit" "--verbose"
__git_alias "$git_reset_alias" "git" "reset" "--"
__git_alias "$git_reset_hard_alias" "git" "reset" "--hard"
__git_alias "$git_rm_alias" "git" "rm"
__git_alias "$git_blame_alias" "git" "blame"
__git_alias "$git_diff_alias" "git" "diff" "--"
__git_alias "$git_diff_word_alias" "git" "diff" "--word-diff"
__git_alias "$git_diff_cached_alias" "git" "diff" "--cached --"
__git_alias "$git_add_patch_alias" "git" "add" "-p"
__git_alias "$git_add_updated_alias" "git" "add" "-u"
__git_alias "$git_difftool_alias" "git" "difftool"
__git_alias "$git_checkout_alias" 'git' 'checkout'
__git_alias "$git_commit_alias" 'git' 'commit'
__git_alias "$git_commit_verbose_alias" 'git' 'commit' '--verbose'
__git_alias "$git_reset_alias" 'git' 'reset'
__git_alias "$git_reset_hard_alias" 'git' 'reset' '--hard'
__git_alias "$git_rm_alias" 'git' 'rm'
__git_alias "$git_blame_alias" 'git' 'blame'
__git_alias "$git_diff_no_whitespace_alias" 'git' 'diff' '-w'
__git_alias "$git_diff_alias" 'git' 'diff'
__git_alias "$git_diff_file_alias" 'git' 'diff'
__git_alias "$git_diff_word_alias" 'git' 'diff' '--word-diff'
__git_alias "$git_diff_cached_alias" 'git' 'diff' '--cached'
__git_alias "$git_add_patch_alias" 'git' 'add' '-p'
__git_alias "$git_add_updated_alias" 'git' 'add' '-u'
__git_alias "$git_difftool_alias" 'git' 'difftool'
# Custom default format for git log
git_log_command="log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)<%an>%Creset' --abbrev-commit"
__git_alias "$git_log_alias" "git" "$git_log_command"
__git_alias "$git_log_alias" 'git' "$git_log_command"
# Same as the above, but displays all the branches and remotes
__git_alias "$git_log_all_alias" "git" "$git_log_command" "--branches" "--remotes"
__git_alias "$git_log_all_alias" 'git' "$git_log_command" '--branches' '--remotes'
# Standard commands
__git_alias "$git_clone_alias" "git" 'clone'
__git_alias "$git_fetch_alias" "git" 'fetch'
__git_alias "$git_checkout_branch_alias" "git" 'checkout' "-b"
__git_alias "$git_pull_alias" "git" 'pull'
__git_alias "$git_push_alias" "git" 'push'
__git_alias "$git_push_force_alias" "git" 'push' '-f'
__git_alias "$git_status_original_alias" "git" 'status' # (Standard git status)
__git_alias "$git_status_short_alias" "git" 'status' '-s'
__git_alias "$git_clean_alias" "git" "clean"
__git_alias "$git_clean_force_alias" "git" "clean" "-fd"
__git_alias "$git_remote_alias" "git" 'remote' '-v'
__git_alias "$git_rebase_alias" "git" 'rebase'
__git_alias "$git_rebase_interactive_alias" "git" 'rebase' "-i"
__git_alias "$git_rebase_alias_continue" "git" 'rebase' "--continue"
__git_alias "$git_rebase_alias_abort" "git" 'rebase' "--abort"
__git_alias "$git_reset_last_commit" "git" "reset HEAD~"
__git_alias "$git_merge_alias" "git" 'merge'
__git_alias "$git_merge_no_fast_forward_alias" "git" "merge" "--no-ff"
__git_alias "$git_merge_only_fast_forward_alias" "git" "merge" "--ff"
__git_alias "$git_cherry_pick_alias" "git" 'cherry-pick'
__git_alias "$git_show_alias" "git" 'show'
__git_alias "$git_show_summary" "git" 'show' '--summary'
__git_alias "$git_stash_alias" "git" 'stash'
__git_alias "$git_stash_apply_alias" "git" 'stash' 'apply'
__git_alias "$git_stash_pop_alias" "git" 'stash' 'pop'
__git_alias "$git_stash_list_alias" "git" 'stash' 'list'
__git_alias "$git_tag_alias" "git" 'tag'
__git_alias "$git_clone_alias" 'git' 'clone'
__git_alias "$git_fetch_alias" 'git' 'fetch'
__git_alias "$git_checkout_branch_alias" 'git' 'checkout' '-b'
__git_alias "$git_pull_alias" 'git' 'pull'
__git_alias "$git_pull_rebase_alias" 'git' 'pull' '--rebase'
__git_alias "$git_push_alias" 'git' 'push'
__git_alias "$git_push_force_alias" 'git' 'push' '-f'
__git_alias "$git_status_original_alias" 'git' 'status' # (Standard git status)
__git_alias "$git_status_short_alias" 'git' 'status' '-s'
__git_alias "$git_clean_alias" 'git' 'clean'
__git_alias "$git_clean_force_alias" 'git' 'clean' '-fd'
__git_alias "$git_remote_alias" 'git' 'remote' '-v'
__git_alias "$git_rebase_alias" 'git' 'rebase'
__git_alias "$git_rebase_interactive_alias" 'git' 'rebase' '-i'
__git_alias "$git_rebase_alias_continue" 'git' 'rebase' '--continue'
__git_alias "$git_rebase_alias_abort" 'git' 'rebase' '--abort'
__git_alias "$git_reset_last_commit" 'git' 'reset HEAD~'
__git_alias "$git_top_level_alias" 'git' 'rev-parse' '--show-toplevel'
__git_alias "$git_merge_alias" 'git' 'merge'
__git_alias "$git_merge_no_fast_forward_alias" 'git' 'merge' '--no-ff'
__git_alias "$git_merge_only_fast_forward_alias" 'git' 'merge' '--ff'
__git_alias "$git_cherry_pick_alias" 'git' 'cherry-pick'
__git_alias "$git_show_alias" 'git' 'show'
__git_alias "$git_show_summary" 'git' 'show' '--summary'
__git_alias "$git_stash_alias" 'git' 'stash'
__git_alias "$git_stash_apply_alias" 'git' 'stash' 'apply'
__git_alias "$git_stash_pop_alias" 'git' 'stash' 'pop'
__git_alias "$git_stash_list_alias" 'git' 'stash' 'list'
__git_alias "$git_tag_alias" 'git' 'tag'
__git_alias "$git_submodule_update_alias" 'git' 'submodule' 'update' '--init'
__git_alias "$git_submodule_update_rec_alias" 'git' 'submodule' 'update' '--init' '--recursive'
__git_alias "$git_whatchanged_alias" 'git' 'whatchanged'
__git_alias "$git_apply_alias" 'git' 'apply'
# Compound/complex commands
_alias $git_fetch_all_alias="git fetch --all"
_alias $git_pull_then_push_alias="git pull && git push"
_alias $git_fetch_and_rebase_alias='git fetch && git rebase'
_alias $git_commit_amend_alias='git commit --amend'
_alias "$git_fetch_all_alias" 'git fetch --all'
_alias "$git_pull_then_push_alias" 'git pull && git push'
_alias "$git_fetch_and_rebase_alias" 'git fetch && git rebase'
_alias "$git_commit_amend_alias" 'git commit --amend'
# Add staged changes to latest commit without prompting for message
_alias $git_commit_amend_no_msg_alias='git commit --amend -C HEAD'
_alias $git_commit_no_msg_alias='git commit -C HEAD'
_alias $git_log_stat_alias='git log --stat --max-count=5'
_alias $git_log_graph_alias='git log --graph --max-count=5'
_alias $git_add_all_alias='git add -A'
_alias "$git_commit_amend_no_msg_alias" 'git commit --amend -C HEAD'
_alias "$git_commit_no_msg_alias" 'git commit -C HEAD'
_alias "$git_log_stat_alias" 'git log --stat --max-count=5'
_alias "$git_log_graph_alias" 'git log --graph --max-count=5'
_alias "$git_add_all_alias" 'git add --all .'
# Hub aliases (https://github.com/github/hub)
_alias "$git_pull_request_alias" 'git pull-request'
fi
@@ -168,4 +190,3 @@ if [ $shell = "bash" ]; then
else
compdef _git_index_tab_completion git_index $git_index_alias
fi

View File

@@ -13,8 +13,9 @@
unalias $git_branch_alias > /dev/null 2>&1; unset -f $git_branch_alias > /dev/null 2>&1
function _scmb_git_branch_shortcuts {
fail_if_not_git_repo || return 1
# Fall back to normal git branch, if any unknown args given
if [[ -n "$@" ]] && [[ "$@" != "-a" ]]; then
if [[ "$($_git_cmd branch | wc -l)" -gt 300 ]] || ([[ -n "$@" ]] && [[ "$@" != "-a" ]]); then
exec_scmb_expand_args $_git_cmd branch "$@"
return 1
fi
@@ -32,14 +33,16 @@ EOF
# Set numbered file shortcut in variable
local e=1
IFS=$'\n'
for branch in $($_git_cmd branch "$@" | sed "s/^[* ]\{2\}//"); do
export $git_env_char$e="$branch"
if [ "${scmbDebug:-}" = "true" ]; then echo "Set \$$git_env_char$e => $file"; fi
let e++
done
unset IFS
}
__git_alias "$git_branch_alias" "_scmb_git_branch_shortcuts"
__git_alias "$git_branch_alias" "_scmb_git_branch_shortcuts" ""
__git_alias "$git_branch_all_alias" "_scmb_git_branch_shortcuts" "-a"
__git_alias "$git_branch_move_alias" "_scmb_git_branch_shortcuts" "-m"
__git_alias "$git_branch_delete_alias" "_scmb_git_branch_shortcuts" "-d"

4
lib/git/fallback/status_shortcuts_shell.sh Normal file → Executable file
View File

@@ -114,7 +114,7 @@ git_status_shortcuts() {
# so just use plain 'git status'
git status
fi
IFS=$' \t\n'
unset IFS
zsh_reset # Reset zsh environment to default
}
# Template function for 'git_status_shortcuts'.
@@ -127,7 +127,7 @@ _gs_output_file_group() {
if [ -z "$project_root" ]; then
relative="${stat_file[$i]}"
else
dest="$project_root/${stat_file[$i]}"
dest=$(readlink -f "$project_root/${stat_file[$i]}")
local pwd=$(readlink -f "$PWD")
relative="$(_gs_relative_path "$pwd" "$dest" )"
fi

47
lib/git/grep_shortcuts.rb Normal file
View File

@@ -0,0 +1,47 @@
#!/usr/bin/env ruby
# encoding: UTF-8
PROJECT_ROOT = File.exist?(".git") ? Dir.pwd : `\git rev-parse --show-toplevel 2> /dev/null`.strip
COLORS = {
:rst => "\033[0m",
:del => "\033[0;31m",
:mod => "\033[0;32m",
:new => "\033[0;33m",
:ren => "\033[0;34m",
:cpy => "\033[0;33m",
:typ => "\033[0;35m",
:unt => "\033[0;36m",
:dark => "\033[2;37m",
:branch => "\033[1m",
:header => "\033[0m"
}
COLOR_MATCH = /\e\[[0-9;]*[mK]/
output_files = []
stdin = STDIN.set_encoding(Encoding::ASCII_8BIT)
while stdin.gets
if $. > 1000
puts "Only showing first 1000 results. Please refine your search."
break
end
print "#{COLORS[:dark]}[#{COLORS[:rst]}#{$.}#{COLORS[:dark]}]#{COLORS[:rst]} "
matches = $_.match(/(^.+?)#{COLOR_MATCH}?:#{COLOR_MATCH}?(\d+)?/)
file = matches[1]
line = matches[2]
output_files << "#{file}#{line ? ":#{line}" : ""}"
puts $_
end
print "@@filelist@@::"
output_files.each_with_index {|f,i|
# If file starts with a '~', treat it as a relative path.
# This is important when dealing with symlinks
print "|" unless i == 0
print f.start_with?("~") ? f.sub(/~/, '') : File.join(PROJECT_ROOT, f)
}
puts

24
lib/git/grep_shortcuts.sh Normal file
View File

@@ -0,0 +1,24 @@
git_grep_shortcuts() {
fail_if_not_git_repo || return 1
git_clear_vars
# Run ruby script, store output
tmp_grep_results="$(git rev-parse --git-dir)/tmp_grep_results_$$"
git grep -n --color=always "$@" |
/usr/bin/env ruby "$scmbDir/lib/git/grep_shortcuts.rb" >"$tmp_grep_results"
# Fetch list of files from last line of script output
files="$(tail -1 "$tmp_grep_results" | sed 's%@@filelist@@::%%g')"
# Export numbered env variables for each file
IFS="|"
local e=1
for file in ${=files}; do
export $git_env_char$e="$file"
let e++
done
IFS=$' \t\n'
# Print status
cat "$tmp_grep_results" | sed '$d' | less -SfRMXFi
rm -f "$tmp_grep_results"
}

View File

@@ -27,13 +27,13 @@ if [[ "$git_keyboard_shortcuts_enabled" = "true" ]]; then
# Uses emacs style keybindings, so vi mode is not supported for now
if ! set -o | grep -q '^vi .*on$'; then
if [[ $shell == "zsh" ]]; then
_bind "$git_commit_all_keys" " git_commit_all""\n"
_bind "$git_add_and_commit_keys" " \033[1~ git_add_and_commit ""\n"
_bind "$git_commit_all_with_ci_skip_keys" " \033[1~ APPEND='[ci skip]' git_commit_all ""\n"
_bind "$git_commit_all_keys" " git_commit_all""^M"
_bind "$git_add_and_commit_keys" " \033[1~ git_add_and_commit ""^M"
_bind "$git_commit_all_with_ci_skip_keys" " \033[1~ APPEND='[ci skip]' git_commit_all ""^M"
else
_bind "$git_commit_all_keys" "\" git_commit_all\n\""
_bind "$git_add_and_commit_keys" "\"\033[1~ git_add_and_commit \n\""
_bind "$git_commit_all_with_ci_skip_keys" "\"\033[1~ APPEND='[ci skip]' git_commit_all \n\""
_bind "$git_commit_all_keys" "\" git_commit_all^M\""
_bind "$git_add_and_commit_keys" "\"\C-A git_add_and_commit ^M\""
_bind "$git_commit_all_with_ci_skip_keys" "\"\C-A APPEND='[ci skip]' git_commit_all ^M\""
fi
fi

View File

@@ -68,8 +68,8 @@ function git_index() {
elif [ "$1" = "--list" ] || [ "$1" = "-l" ]; then
echo -e "$_bld_col$(_git_index_count)$_txt_col Git repositories in $_bld_col$GIT_REPO_DIR$_txt_col:\n"
for repo in $(_git_index_dirs_without_home); do
echo $(basename $repo) : $repo
done | sort | column -t -s ':'
echo $(basename $repo | sed "s/ /_/g") : $repo
done | sort -t ":" -k1,1 | column -t -s ':'
elif [ "$1" = "--count-by-host" ]; then
echo -e "=== Producing a report of the number of repos per host...\n"
_git_index_batch_cmd git remote -v | \grep "origin.*(fetch)" |
@@ -116,7 +116,7 @@ function git_index() {
fi
fi
fi
IFS=$' \t\n'
unset IFS
}
_git_index_dirs_without_home() {
@@ -127,11 +127,11 @@ _git_index_dirs_without_home() {
function _find_git_repos() {
# Find all unarchived projects
IFS=$'\n'
for repo in $(find -L "$GIT_REPO_DIR" -maxdepth 4 -name ".git" -type d \! -wholename '*/archive/*'); do
for repo in $(find -L "$GIT_REPO_DIR" -maxdepth 5 -name ".git" -type d \! -wholename '*/archive/*'); do
echo ${repo%/.git} # Return project folder, with trailing ':'
_find_git_submodules $repo # Detect any submodules
done
IFS=$' \t\n'
unset IFS
}
# List all submodules for a git repo, if any.
@@ -148,9 +148,9 @@ function _rebuild_git_index() {
# Get repos from src dir and custom dirs, then sort by basename
IFS=$'\n'
for repo in $(echo -e "$(_find_git_repos)\n$(echo $GIT_REPOS | sed "s/:/\\\\n/g")"); do
echo $(basename $repo | sed "s/ /_/g") $repo
done | sort | cut -d " " -f2- > "$GIT_REPO_DIR/.git_index"
IFS=$' \t\n'
echo $(basename $repo | sed "s/ /_/g"):$repo
done | sort -t ":" -k1,1 | cut -d ":" -f2- >| "$GIT_REPO_DIR/.git_index"
unset IFS
if [ "$1" != "--silent" ]; then
echo -e "===== Indexed $_bld_col$(_git_index_count)$_txt_col repos in $GIT_REPO_DIR/.git_index"
@@ -225,7 +225,7 @@ _git_index_update_all_branches() {
echo "=== Skipping $branch: remote and merge refs are not configured."
fi
done
IFS=$' \t\n'
unset IFS
# Update all remotes if there are any branches to update
if [ -n "${branches[*]}" ]; then git fetch --all 2> /dev/null; fi
@@ -268,7 +268,7 @@ function _git_index_batch_cmd() {
cwd="$PWD"
if [ -n "$1" ]; then
echo -e "== Running command for $_bld_col$(_git_index_count)$_txt_col repos...\n"
IFS=$' \t\n'
unset IFS
local base_path
for base_path in $(sed -e "s/--.*//" "$GIT_REPO_DIR/.git_index" | \grep . | sort); do
builtin cd "$base_path"
@@ -313,7 +313,7 @@ if [ $shell = 'bash' ]; then
else
COMPREPLY=($(compgen -W '$(sed -e "s:.*/::" -e "s:$:/:" "$GIT_REPO_DIR/.git_index" | sort)' -- $curw))
fi
IFS=$' \t\n'
unset IFS
return 0
}
else

View File

@@ -5,9 +5,9 @@
# ------------------------------------------------------------------------------
if test | sed -E 's///g' 2>/dev/null; then
if sed -E 's///g' </dev/null &>/dev/null; then
SED_REGEX_ARG="E"
elif test | sed -r 's///g' 2>/dev/null; then
elif sed -r 's///g' </dev/null &>/dev/null; then
SED_REGEX_ARG="r"
else
echo "Cannot determine extended regex argument for sed! (Doesn't respond to either -E or -r)"
@@ -21,7 +21,7 @@ if [ "$shell_command_wrapping_enabled" = "true" ] || [ "$bash_command_wrapping_e
# Do it in a function so we don't bleed variables
function _git_wrap_commands() {
# Define 'whence' for bash, to get the value of an alias
type whence > /dev/null 2>&1 || function whence() { type "$@" | sed -$SED_REGEX_ARG -e "s/.*is aliased to \`//" -e "s/'$//"; }
type whence > /dev/null 2>&1 || function whence() { LC_MESSAGES="C" type "$@" | sed -$SED_REGEX_ARG -e "s/.*is aliased to \`//" -e "s/'$//"; }
local cmd=''
for cmd in $(echo $scmb_wrapped_shell_commands); do
if [ "${scmbDebug:-}" = "true" ]; then echo "SCMB: Wrapping $cmd..."; fi
@@ -35,7 +35,7 @@ if [ "$shell_command_wrapping_enabled" = "true" ] || [ "$bash_command_wrapping_e
fi
fi
case "$(type $cmd 2>&1)" in
case "$(LC_MESSAGES="C" type $cmd 2>&1)" in
# Don't do anything if command already aliased, or not found.
*'exec_scmb_expand_args'*)
@@ -52,7 +52,7 @@ if [ "$shell_command_wrapping_enabled" = "true" ] || [ "$bash_command_wrapping_e
unalias $cmd
# Detect original $cmd type, and escape
case "$(type $cmd 2>&1)" in
case "$(LC_MESSAGES="C" type $cmd 2>&1)" in
# Escape shell builtins with 'builtin'
*'is a shell builtin'*) local escaped_cmd="builtin $cmd";;
# Get full path for files with 'find_binary' function
@@ -108,8 +108,9 @@ fi
# Function wrapper around 'll'
# Adds numbered shortcuts to output of ls -l, just like 'git status'
unalias ll > /dev/null 2>&1; unset -f ll > /dev/null 2>&1
function ls_with_file_shortcuts {
if [ "$shell_ls_aliases_enabled" = "true" ] && which ruby > /dev/null 2>&1; then
unalias ll > /dev/null 2>&1; unset -f ll > /dev/null 2>&1
function ls_with_file_shortcuts {
local ll_output
if [ "$_ls_bsd" != "BSD" ]; then
ll_output="$(\ls -lhv --group-directories-first --color "$@")"
@@ -124,11 +125,11 @@ function ls_with_file_shortcuts {
fi
# Parse path from args
OLDIFS="$IFS"; IFS=$'\n'
IFS=$'\n'
for arg in $@; do
if [ -d "$arg" ]; then local rel_path="${arg%/}"; fi
done
IFS="$OLDIFS"
unset IFS
# Replace user/group with user symbol, if defined at ~/.user_sym
# Before : -rw-rw-r-- 1 ndbroadbent ndbroadbent 1.1K Sep 19 21:39 scm_breeze.sh
@@ -174,19 +175,20 @@ EOF
ll_files="$(\ls "$@")"
fi
OLDIFS="$IFS"; IFS=$'\n'
IFS=$'\n'
for file in $ll_files; do
if [ -n "$rel_path" ]; then file="$rel_path/$file"; fi
export $git_env_char$e="$(eval $_abs_path_command \"${file//\"/\\\"}\")"
if [ "${scmbDebug:-}" = "true" ]; then echo "Set \$$git_env_char$e => $file"; fi
let e++
done
IFS="$OLDIFS"
unset IFS
# Turn off shwordsplit unless it was on previously
if [[ $shell == "zsh" ]] && [ -z "$SHWORDSPLIT_ON" ]; then unsetopt shwordsplit; fi
}
}
# Setup aliases
alias ll="exec_scmb_expand_args ls_with_file_shortcuts"
alias la="ll -A"
# Setup aliases
alias ll="exec_scmb_expand_args ls_with_file_shortcuts"
alias la="ll -A"
fi

View File

@@ -43,7 +43,7 @@ git_status_shortcuts() {
if [ "${scmbDebug:-}" = "true" ]; then echo "Set \$$git_env_char$e => $file"; fi
let e++
done
IFS=$' \t\n'
unset IFS
if [ "${scmbDebug:-}" = "true" ]; then echo "------------------------"; fi
# Print status
@@ -91,7 +91,7 @@ git_silent_add_shortcuts() {
echo -e "# Added '$file'"
fi
done
IFS=$' \t\n'
unset IFS
echo "#"
fi
}
@@ -158,7 +158,7 @@ _print_path() {
# Execute a command with expanded args, e.g. Delete files 6 to 12: $ ge rm 6-12
# Fails if command is a number or range (probably not worth fixing)
exec_scmb_expand_args() {
eval "$(scmb_expand_args "$@" | sed -e "s/\([][()<>^ \"']\)/"'\\\1/g')"
eval "$(scmb_expand_args "$@" | sed -e "s/\([][|;()<>^ \"'&]\)/"'\\\1/g')"
}
# Clear numbered env variables
@@ -166,7 +166,12 @@ git_clear_vars() {
local i
for (( i=1; i<=$gs_max_changes; i++ )); do
# Stop clearing after first empty var
if [[ -z "$(eval echo "\${$git_env_char$i:-}")" ]]; then break; fi
local env_var_i=${git_env_char}${i}
if [[ -z "$(eval echo "\${$env_var_i:-}")" ]]; then
break
else
unset $env_var_i
fi
done
}
@@ -181,7 +186,7 @@ _git_resolve_merge_conflict() {
git add "$file"
echo -e "# Added $1 version of '$file'"
done
IFS=$' \t\n'
unset IFS
echo -e "# -- If you have finished resolving conflicts, commit the resolutions with 'git commit'"
fi
}
@@ -233,7 +238,7 @@ git_commit_all() {
local appending=" | \033[0;36mappending '\033[1;36m$APPEND\033[0;36m' to commit message.\033[0m"
fi
echo -e "\033[0;33mCommitting all files (\033[0;31m$changes\033[0;33m)\033[0m$appending"
git_commit_prompt "git add -A"
git_commit_prompt "git add --all ."
else
echo "# No changed files to commit."
fi

View File

View File

@@ -10,7 +10,13 @@ enable_nullglob() { if [ $shell = "zsh" ]; then setopt NULL_GLOB; else shopt
disable_nullglob() { if [ $shell = "zsh" ]; then unsetopt NULL_GLOB; else shopt -u nullglob; fi; }
# Alias wrapper that ignores errors if alias is not defined.
_alias(){ alias "$@" 2> /dev/null; }
_safe_alias(){ alias "$@" 2> /dev/null; }
_alias() {
if [ -n "$1" ]; then
local alias_str="$1"; local cmd="$2"
_safe_alias $alias_str="$cmd"
fi
}
find_binary(){
if [ $shell = "zsh" ]; then
@@ -48,7 +54,7 @@ _create_or_patch_scmbrc() {
# If file exists, attempt to update it with any new settings
elif [ -n "$1" ]; then
# Create diff of example file, substituting example file for user's config.
git diff $1 "$prefix""scmbrc.example" | sed "s/$prefix""scmbrc.example/.$prefix""scmbrc/g" > $patchfile
git diff $1 "$prefix""scmbrc.example" | sed "s/$prefix""scmbrc.example/.$prefix""scmbrc/g" >| $patchfile
if [ -s $patchfile ]; then # If patchfile is not empty
cd "$HOME"
# If the patch cannot be applied cleanly, show the updates and tell user to update file manually.

View File

View File

@@ -3,8 +3,15 @@
failed=false
# allow list of shells to run tests in to be overriden by environment variable
# if empty or null, use defaults
if [ -z "$TEST_SHELLS" ]; then
TEST_SHELLS="bash zsh"
fi
echo "== Will run all tests with following shells: ${TEST_SHELLS}"
for test in $(find test/lib -name *_test.sh); do
for shell in bash zsh; do
for shell in $TEST_SHELLS; do
echo "== Running tests with [$shell]: $test"
$shell $test || failed=true
done
@@ -12,8 +19,8 @@ done
if [ "$failed" = "true" ]; then
echo "Tests failed!"
return 1;
false
else
echo "All tests passed!"
return 0;
true
fi

25
scm_breeze.plugin.zsh Normal file
View File

@@ -0,0 +1,25 @@
#########################################################
# Forked from http://github.com/ndbroadbent/scm_breeze #
# #
# File Copied and modified from ./install.sh #
# to be compatible with oh-my-zsh's plugin system #
#########################################################
#!/bin/bash
#locate the dir where this script is stored
export scmbDir="$( cd -P "$( dirname "$0" )" && pwd )"
# Symlink to ~/.scm_breeze if installing from another path
if [ ! -s "$HOME/.scm_breeze" ] && [ "$scmbDir" != "$HOME/.scm_breeze" ]; then
ln -fs "$scmbDir" "$HOME/.scm_breeze"
# Load SCM Breeze update scripts
source "$scmbDir/lib/scm_breeze.sh"
# Create '~/.*.scmbrc' files from example files
_create_or_patch_scmbrc
fi
# This loads SCM Breeze into the shell session.
[ -s "$HOME/.scm_breeze/scm_breeze.sh" ] && source "$HOME/.scm_breeze/scm_breeze.sh"

View File

@@ -22,6 +22,7 @@ if [[ -s "$HOME/.git.scmbrc" ]]; then
source "$scmbDir/lib/git/keybindings.sh"
source "$scmbDir/lib/git/status_shortcuts.sh"
source "$scmbDir/lib/git/branch_shortcuts.sh"
source "$scmbDir/lib/git/grep_shortcuts.sh"
source "$scmbDir/lib/git/shell_shortcuts.sh"
source "$scmbDir/lib/git/repo_index.sh"
source "$scmbDir/lib/git/tools.sh"

View File

@@ -7,10 +7,14 @@
#
# Unit tests for git shell scripts
export scmbDir="$( cd -P "$( dirname "$0" )" && pwd )/../../.."
export scmbDir="$(cd -P "$(dirname "$0")" && pwd)/../../.."
# Zsh compatibility
if [ -n "${ZSH_VERSION:-}" ]; then shell="zsh"; SHUNIT_PARENT=$0; setopt shwordsplit; fi
if [ -n "${ZSH_VERSION:-}" ]; then
shell="zsh"
SHUNIT_PARENT=$0
setopt shwordsplit
fi
# Load test helpers
source "$scmbDir/test/support/test_helper.sh"
@@ -19,7 +23,6 @@ source "$scmbDir/test/support/test_helper.sh"
source "$scmbDir/lib/scm_breeze.sh"
source "$scmbDir/lib/git/repo_index.sh"
# Setup and tear down
#-----------------------------------------------------------------------------
oneTimeSetUp() {
@@ -34,7 +37,10 @@ oneTimeSetUp() {
cd $GIT_REPO_DIR
# Setup test repos in temp repo dir
for repo in github bitbucket source_forge TestCaps; do
mkdir $repo; cd $repo; git init; cd - > /dev/null
mkdir $repo
cd $repo
git init
cd - >/dev/null
done
# Add some nested dirs for testing resursive tab completion
@@ -47,7 +53,7 @@ oneTimeSetUp() {
mkdir submodules_everywhere
cd submodules_everywhere
git init
cat > .gitmodules <<EOF
cat >.gitmodules <<EOF
[submodule "very/nested/directory/red_submodule"]
[submodule "very/nested/directory/green_submodule"]
[submodule "very/nested/directory/blue_submodule"]
@@ -55,15 +61,20 @@ EOF
mkdir -p "very/nested/directory"
cd "very/nested/directory"
for repo in red_submodule green_submodule blue_submodule; do
mkdir $repo; cd $repo; git init; cd - > /dev/null
mkdir $repo
cd $repo
git init
cd - >/dev/null
done
# Setup some custom repos outside the main repo dir
IFS=":"
for dir in $GIT_REPOS; do
mkdir -p $dir; cd $dir; git init;
mkdir -p $dir
cd $dir
git init
done
IFS=$' \t\n'
unset IFS
verboseGitCommands
@@ -74,7 +85,7 @@ oneTimeTearDown() {
rm -rf "${GIT_REPO_DIR}"
IFS=":"
for dir in $GIT_REPOS; do rm -rf $dir; done
IFS=$' \t\n'
unset IFS
}
ensureIndex() {
@@ -85,30 +96,32 @@ index_no_newlines() {
tr "\\n" " " < $git_index_file
}
#-----------------------------------------------------------------------------
# Unit tests
#-----------------------------------------------------------------------------
test_repo_index_command() {
git_index --rebuild > /dev/null
git_index --rebuild >/dev/null
# Test that all repos are detected, and sorted alphabetically
assertIncludes "$(index_no_newlines)" "bitbucket.*\
blue_submodule.*\
github.*\
green_submodule.*\
red_submodule.*\
source_forge.*\
submodules_everywhere.*\
test_repo_11.*\
test_repo_1"
assertIncludes "$(index_no_newlines)" $(
cat <<EXPECT | sort -t "." -k1,1 | tr -d '\n' | awk '{print ".*"$1}'
bitbucket.*
blue_submodule.*
github.*
green_submodule.*
red_submodule.*
source_forge.*
submodules_everywhere.*
test_repo_11.*
test_repo_1.*
EXPECT
)
}
test_check_git_index() {
ensureIndex
echo "should not be regenerated" >> $git_index_file
echo "should not be regenerated" >>$git_index_file
_check_git_index
# Test that index is not rebuilt unless empty
assertIncludes "$(index_no_newlines)" "should not be regenerated"
@@ -133,16 +146,26 @@ test_repo_list() {
# Test matching rules for changing directory
test_git_index_changing_directory() {
ensureIndex
git_index "github"; assertEquals "$GIT_REPO_DIR/github" "$PWD"
git_index "github/"; assertEquals "$GIT_REPO_DIR/github" "$PWD"
git_index "bucket"; assertEquals "$GIT_REPO_DIR/bitbucket" "$PWD"
git_index "testcaps"; assertEquals "$GIT_REPO_DIR/TestCaps" "$PWD"
git_index "green_sub"; assertEquals "$GIT_REPO_DIR/submodules_everywhere/very/nested/directory/green_submodule" "$PWD"
git_index "_submod"; assertEquals "$GIT_REPO_DIR/submodules_everywhere/very/nested/directory/blue_submodule" "$PWD"
git_index "test_repo_1"; assertEquals "/tmp/test_repo_1" "$PWD"
git_index "test_repo_11"; assertEquals "/tmp/test_repo_11" "$PWD"
git_index "test_repo_"; assertEquals "/tmp/test_repo_11" "$PWD"
git_index "github/videos/octocat/live_action"; assertEquals "$GIT_REPO_DIR/github/videos/octocat/live_action" "$PWD"
git_index "github"
assertEquals "$GIT_REPO_DIR/github" "$PWD"
git_index "github/"
assertEquals "$GIT_REPO_DIR/github" "$PWD"
git_index "bucket"
assertEquals "$GIT_REPO_DIR/bitbucket" "$PWD"
git_index "testcaps"
assertEquals "$GIT_REPO_DIR/TestCaps" "$PWD"
git_index "green_sub"
assertEquals "$GIT_REPO_DIR/submodules_everywhere/very/nested/directory/green_submodule" "$PWD"
git_index "_submod"
assertEquals "$GIT_REPO_DIR/submodules_everywhere/very/nested/directory/blue_submodule" "$PWD"
git_index "test_repo_1"
assertEquals "/tmp/test_repo_1" "$PWD"
git_index "test_repo_11"
assertEquals "/tmp/test_repo_11" "$PWD"
git_index "test_repo_"
assertEquals "/tmp/test_repo_1" "$PWD"
git_index "github/videos/octocat/live_action"
assertEquals "$GIT_REPO_DIR/github/videos/octocat/live_action" "$PWD"
}
test_git_index_tab_completion() {
@@ -172,7 +195,6 @@ test_git_index_tab_completion() {
_git_index_tab_completion
assertIncludes "$(tab_completions)" "github/videos/octocat/"
# Test that completion checks for other matching projects even if one matches perfectly
COMP_WORDS="test_repo_1"
_git_index_tab_completion
@@ -180,7 +202,6 @@ test_git_index_tab_completion() {
fi
}
# Test changing to top-level directory (when arg begins with '/')
test_changing_to_top_level_directory() {
mkdir "$GIT_REPO_DIR/gems"
@@ -188,8 +209,6 @@ test_changing_to_top_level_directory() {
assertEquals "$GIT_REPO_DIR/gems" "$PWD"
}
# load and run shUnit2
# Call this function to run tests
source "$scmbDir/test/support/shunit2"

View File

@@ -21,22 +21,38 @@ fi
source "$scmbDir/test/support/test_helper.sh"
source "$scmbDir/lib/scm_breeze.sh"
bin_path() {
if [ -n "${ZSH_VERSION:-}" ];
then where "$@" | tail -1
else which "$@"
fi
}
# Setup
#-----------------------------------------------------------------------------
oneTimeSetUp() {
export shell_command_wrapping_enabled="true"
export scmb_wrapped_shell_commands="not_found cat rm cp mv ln cd sed"
export shell_ls_aliases_enabled="true"
alias rvm="test" # Ensure tests run if RVM isn't loaded but $HOME/.rvm is present
# Test functions
function ln() { ln $@; }
# Before aliasing, get original locations so we can compare them in the test
unalias mv rm sed cat 2>/dev/null
export mv_path="$(bin_path mv)"
export rm_path="$(bin_path rm)"
export sed_path="$(bin_path sed)"
export cat_path="$(bin_path cat)"
# Test aliases
alias mv="nocorrect mv"
alias rm="rm --option"
alias sed="sed"
alias mv="nocorrect $mv_path"
alias rm="$rm_path --option"
alias sed="$sed_path"
# Test already wrapped commands
alias cat="exec_scmb_expand_args /bin/cat"
alias cat="exec_scmb_expand_args $cat_path"
# Run shortcut wrapping
source "$scmbDir/lib/git/shell_shortcuts.sh"
@@ -58,10 +74,10 @@ assertAliasEquals(){
#-----------------------------------------------------------------------------
test_shell_command_wrapping() {
assertAliasEquals "exec_scmb_expand_args /bin/rm --option" "rm"
assertAliasEquals "exec_scmb_expand_args nocorrect /bin/mv" "mv"
assertAliasEquals "exec_scmb_expand_args /bin/sed" "sed"
assertAliasEquals "exec_scmb_expand_args /bin/cat" "cat"
assertAliasEquals "exec_scmb_expand_args nocorrect $mv_path" "mv"
assertAliasEquals "exec_scmb_expand_args $rm_path --option" "rm"
assertAliasEquals "exec_scmb_expand_args $sed_path" "sed"
assertAliasEquals "exec_scmb_expand_args $cat_path" "cat"
assertAliasEquals "exec_scmb_expand_args builtin cd" "cd"
assertIncludes "$(declare -f ln)" "ln ()"
assertIncludes "$(declare -f ln)" "exec_scmb_expand_args __original_ln"
@@ -71,7 +87,15 @@ test_ls_with_file_shortcuts() {
export git_env_char="e"
TEST_DIR=$(mktemp -d -t scm_breeze.XXXXXXXXXX)
# Darwin actually symlinks /var inside /private, but mktemp reports back the
# logical pathat time of file creation. So make sure we always get the
# full physical path to be absolutely certain when doing comparisons later,
# because thats how the Ruby status_shortcuts.rb script is going to obtain
# them.
cd $TEST_DIR
TEST_DIR=$(pwd -P)
touch 'test file' 'test_file'
mkdir -p "a [b]" 'a "b"' "a 'b'"
touch "a \"b\"/c"
@@ -82,7 +106,7 @@ test_ls_with_file_shortcuts() {
ls_with_file_shortcuts > $temp_file
ls_output=$(<$temp_file strip_colors)
# Compare as fixed strings (F), instead of regex (P)
# Compare as fixed strings (F), instead of normal grep behavior
assertIncludes "$ls_output" '[1] a "b"' F
assertIncludes "$ls_output" "[2] a 'b'" F
assertIncludes "$ls_output" '[3] a [b]' F

View File

@@ -29,6 +29,7 @@ oneTimeSetUp() {
export ga_auto_remove="yes"
testRepo=$(mktemp -d -t scm_breeze.XXXXXXXXXX)
testRepo=$(cd $testRepo && pwd -P)
}
oneTimeTearDown() {
@@ -60,6 +61,10 @@ test_scmb_expand_args() {
"$(scmb_expand_args -ma "Test Commit Message" "Unquoted")"
}
test_command_wrapping_escapes_special_characters() {
assertEquals 'should escape | the pipe' "$(exec_scmb_expand_args echo "should escape | the pipe")"
assertEquals 'should escape ; the semicolon' "$(exec_scmb_expand_args echo "should escape ; the semicolon")"
}
test_git_status_shortcuts() {
setupTestRepo
@@ -312,4 +317,3 @@ test_adding_files_with_spaces() {
# load and run shUnit2
source "$scmbDir/test/support/shunit2"

View File

@@ -15,7 +15,7 @@ fi
# Strip color codes from a string
strip_colors() {
sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g"
perl -pe 's/\e\[[\d;]*m//g'
}
# Print space separated tab completion options
@@ -34,7 +34,7 @@ verboseGitCommands() {
#-----------------------------------------------------------------------------
_includes() {
if [ -n "$3" ]; then regex="$3"; else regex=P; fi
if [ -n "$3" ]; then regex="$3"; else regex=''; fi
if echo "$1" | grep -q$regex "$2"; then echo 0; else echo 1; fi
}
@@ -46,4 +46,3 @@ assertIncludes() {
assertNotIncludes() {
assertFalse "'$1' should not have contained '$2'" $(_includes "$@")
}

32
test/support/travisci_deps.sh Executable file
View File

@@ -0,0 +1,32 @@
#!/usr/bin/env bash
# Installs dependencies for travis-ci environments.
# Install dependencies, which looks to be just bash & zsh.
#
# Darwin has zsh preinstalled already, so only need to install on Ubuntu.
#
# Note: $TRAVIS_OS_NAME will only be set on text boxes with multi-os enabled,
# so use negation test so it will fail gracefully on normal Travis linux setup.
if [[ "$TRAVIS_OS_NAME" != "osx" ]]; then
# okay, so we know we're probably on a linux box (or at least not an osx box)
# at this point. do we need to install zsh? let's say the default case is no:
needs_zsh=false
# check if zsh is listed in the TEST_SHELLS environment variable, set by
# our travis-ci build matrix.
if [[ $TEST_SHELLS =~ zsh ]]; then needs_zsh=true; fi
# if there is NO $TEST_SHELLS env variable persent (which should never happen,
# but maybe someone has been monkeying with the .travis.yml), run_tests.sh is
# going to fall back onto the default of testing everything, so we need zsh.
if [[ -z "$TEST_SHELLS" ]]; then needs_zsh=true; fi
# finally, we install zsh if needed!
if $needs_zsh ; then
sudo apt-get install zsh
else
echo "No deps required."
fi
fi

View File

@@ -1,7 +1,15 @@
#!/bin/sh
# uninstall by (github: bernardofire)
# Remove line from bashrc and zshrc if present.
sed="sed -i"
if [[ $OSTYPE == "Darwin" ]]; then
sed="sed -i ''"
fi
for rc in bashrc zshrc; do
sed -i '/scm_breeze/d' "$HOME/.$rc"
printf "== Removed SCM Breeze from '$HOME/.$rc'\n"
if [ -f "$HOME/.$rc" ]; then
$sed '/scm_breeze/d' "$HOME/.$rc" &&
printf "Removed SCM Breeze from %s\n" "$HOME/.$rc"
fi
done