I am having trouble with bash_completion. When I expand variables, I am fine, but when I use a commands completion (such as git or vim-addon-manager), then the completion throws random characters in there. This didn't use to happen to me, I can't figure out what it is.
This is an example of what happens when I type gitTabTaby
[11:11] me#my_computer:~ $ git
Display all 131 possibilities? (y or n)
^[[01;31m^[[K c^[[m^[[Kheckout delete-tag f^[[m^[[Kmt-merge-msg i^[[m^[[Knit-db notes rm
a^[[m^[[Kdd c^[[m^[[Kheckout-index d^[[m^[[Kaemon f^[[m^[[Kor-each-ref i^[[m^[[Knstaweb obliterate setup
a^[[m^[[Klias c^[[m^[[Kheck-ref-format d^[[m^[[Kelete-branch f^[[m^[[Kormat-patch info p4 shortlog
a^[[m^[[Km c^[[m^[[Kherry d^[[m^[[Kelete-merged-branches f^[[m^[[Ksck line-summary pull show
a^[[m^[[Knnotate c^[[m^[[Kherry-pick d^[[m^[[Kelete-submodule f^[[m^[[Ksck-objects l^[[m^[[Kog pull-request show-branch
a^[[m^[[Kpply c^[[m^[[Klean d^[[m^[[Kescribe fresh-branch l^[[m^[[Ks-files push show-tree
a^[[m^[[Krchive c^[[m^[[Klone d^[[m^[[Kiff g^[[m^[[Kc l^[[m^[[Ks-remote rebase squash
a^[[m^[[Krchive-file c^[[m^[[Kolumn d^[[m^[[Kiff-files g^[[m^[[Ket-tar-commit-id l^[[m^[[Ks-tree refactor stage
b^[[m^[[Kack c^[[m^[[Kommit d^[[m^[[Kiff-index g^[[m^[[Krep local-commits reflog stash
b^[[m^[[Kisect c^[[m^[[Kommits-since d^[[m^[[Kifftool graft mergetool release status
b^[[m^[[Klame c^[[m^[[Kommit-tree d^[[m^[[Kiff-tree h^[[m^[[Kash-object m^[[m^[[Kailinfo relink submodule
b^[[m^[[Kranch c^[[m^[[Konfig effort h^[[m^[[Kelp m^[[m^[[Kailsplit remote subtree
b^[[m^[[Kug c^[[m^[[Kontrib extras h^[[m^[[Kttp-backend m^[[m^[[Kerge rename-tag summary
b^[[m^[[Kundle c^[[m^[[Kount feature h^[[m^[[Kttp-fetch m^[[m^[[Kerge-base repack tag
c^[[m^[[Kat-file c^[[m^[[Kount-objects f^[[m^[[Kast-export h^[[m^[[Kttp-push m^[[m^[[Kerge-file repl touch
c^[[m^[[Khangelog c^[[m^[[Kreate-branch f^[[m^[[Kast-import ignore m^[[m^[[Kerge-index replace undo
c^[[m^[[Kheck-attr c^[[m^[[Kredential f^[[m^[[Ketch i^[[m^[[Kmap-send m^[[m^[[Kerge-octopus request-pull whatchanged
c^[[m^[[Kheck-ignore c^[[m^[[Kredential-cache f^[[m^[[Ketch-pack i^[[m^[[Kndex-pack mv reset
c^[[m^[[Kheck-mailmap c^[[m^[[Kredential-store f^[[m^[[Kilter-branch i^[[m^[[Knit name-rev revert
Another example is vam tetris (vam tetTabTab):
^[[01;31m^[[Kaddon: tet^[[m^[[Kris
For vam install tetTabTab, it actually renders it an invalid argument (it's also quite difficult to read), so how can I fix this?
I was experiencing the same problem and saw your answer and changed:
export GREP_OPTIONS='--color=always' to export GREP_OPTIONS='--color=auto'This seems to have fixed the problem with bash-completion on my Mac.
Apparently, bash completions don't like when grep is colored. Anything like
alias grep='grep --color=always'
alias fgrep='fgrep --color=always'
alias egrep='egrep --color=always'
will give you problems.
Therefore, as Garrett Bellomy details below, it may be wise to use --color=auto, which can be achieved by setting GREP_OPTIONS (or by aliasing grep in your rc file). If you want to make this a global variable, add this to ~/.bash_profile (for bash) or ~/.zprofile (zsh) depending on your default shell: export GREP_OPTIONS='--color=auto'
Related
I'm trying to extract list of commit messages by giving a start sha & end sha. It's easy in git using git log.
But am trying to do it through gitpython library.
Could someone help me to achieve this?
in Git the command is like this :
git log --oneline d3513dbb9f5..598d268f
how do i do it with gitpython?
The GitPython Repo.iter_commits() function (docs) has support for ref-parse-style commit ranges. So you can do:
import git
repo = git.Repo("/path/to/your/repo")
commits = repo.iter_commits("d3513dbb9f5..598d268f")
Everything after that depends on the exact formatting you want to get. If you want something similar to git log --oneline, that would do the trick (it is a simplified form, the tag/branch names are not shown):
for commit in commits:
print("%s %s" % (commit.hexsha, commit.message.splitlines()[0]))
You can use pure gitpython:
import git
repo = git.Repo("/home/user/.emacs.d") # my .emacs repo just for example
logs = repo.git.log("--oneline", "f5035ce..f63d26b")
will give you:
>>> logs
'f63d26b Fix urxvt name to match debian repo\n571f449 Add more key for helm-org-rifle\nbea2697 Drop bm package'
if you want nice output, use pretty print:
from pprint import pprint as pp
>>> pp(logs)
('f63d26b Fix urxvt name to match debian repo\n'
'571f449 Add more key for helm-org-rifle\n'
'bea2697 Drop bm package')
Take a note that logs is str if you want to make it a list, just
use logs.splitlines()
Gitpython had pretty much all similar API with git. E.g repo.git.log for git log and repo.git.show for git show. Learn more in Gitpython API Reference
You may want to try PyDriller (a wrapper around GitPython), it's easier:
for commit in Repository("path_to_repo", from_commit="STARTING COMMIT", to_commit="ENDING_COMMIT").traverse_commits():
print(commit.msg)
If you want commits of a specific branch, add the parameter only_in_branch="BRANCH_NAME". Docs: http://pydriller.readthedocs.io/en/latest/
When I hit gem push <tab>, it displays this error (regardless of whether the directory contains any .gem files):
_arguments:comparguments:325: doubled rest argument definition: *:gem:_files -g "*.gem(-.)"
_arguments:comparguments:325: doubled rest argument definition: *:gem:_files -g "*.gem(-.)"
_arguments:comparguments:325: doubled rest argument definition: *:gem:_files -g "*.gem(-.)"
I have no idea how to fix this and Google is no help. My fpath:
> echo $fpath
/Users/robenkleene/.zsh/completion
/usr/local/share/zsh/site-functions
/usr/local/Cellar/zsh/5.7/share/zsh/functions
I've tried uninstalling and re-installed Ruby via homebrew because the above "Cellar" path contains a _gem file that I believe defines this completion function, but that didn't work.
Any other ideas? Thanks!
(Also, if anyone has any suggestions of where I might file a bug report for this that would also be helpful, thanks again!)
I hacked together my own terrible solution to this but it's better than nothing.
I copied the _gem file from /usr/local/Cellar/zsh/5.7/share/zsh/functions to /Users/robenkleene/.zsh/completion and then modified the offending line (note that this only works because I have fpath=(~/.zsh/completion $fpath) in my zshrc):
- args+=( '*:gem:_files -g "*.gem(-.)"' )
+ args=( '*:gem:_files -g "*.gem(-.)"' )
So I removed the +. This seems to work, but I'd love a more elegant solution and/or any information about why (based on my Google search), I seem to be the only person experiencing this.
I'm on macOS 10.15.6 running the default zsh 5.7.1. In the default zsh gem completion I found that push is being included in a list of commands which take a remote gem name — and it shouldn't be, it only takes the path to the gem file:
$ gem push --help
Usage: gem push GEM [options]
I applied the following patch to a copy of the file higher in $fpath and it now works for me:
--- /usr/share/zsh/5.7.1/functions/_gem
+++ ~/.zsh/completion.d/_gem
## -56,7 +56,7 ##
check|cleanup|contents|dependency|list|open|pristine|rdoc|uninstall|unpack|update)
args+=( '(--all --skip)*:installed gem:->gems-local' )
;|
- fetch|install|lock|owner|push|search|yank)
+ fetch|install|lock|owner|search|yank)
args+=( '*:gem:->gems-remote' )
;|
cleanup|uninstall)
I'm not sure where to contribute this patch. 😅
my end goal is to parse a visual studio team services ssh git url and use it to clone origin and my fork. I'm in windows and I use git bash I've made a few shell scripts to help me to clone it. Before when we used gitweb it was easy for me to parse as I could either run git_clone myproject or git_clone myproject.git or git_clone git://ourgitserver.ourcompany.com/myproject.git and the script would clone the above as origin and also add a remote with my user name in the form of ssh://git#outgitserver.ourcompany.com/myproject.git (and it handled name spaces well too). Well we started using vsts and I want to do the same thing.
The git_clone method changed a few times because of how people would tell/im/email me the link for the git project. I wanted to be able to just copy and paste it with minimal changes. thus far I have a simple git_vsts_close which requires two parameters the name of the project and the name of the repository. (in gitweb we would reference the namespace as vsts's project and the project would be vsts's repository). For the time being I'd like to take either the ssh url or the two parameters and do all the git things. in brief this is what i have so far
function git_vsts_clone {
local projectName=$1
local repositoryName=$2
if MISSING_ARG "usage: git_vsts_clone <project name> <repositoryName>\n projectName must be provided\n repositoryName must be provided" $projectName; then return 1; fi;
if MISSING_ARG "usage: git_vsts_clone <project name> <repositoryName>\n projectName must be provided\n repositoryName must be provided" $repositoryName; then return 1; fi;
local gitServer="ssh://mycompany#vs-ssh.visualstudio.com:22/${projectName}/_ssh/${repositoryName}"
local clonePath="/c/git/${projectName}/${repositoryName}"
local user_name=${USER:-${USERNAME}}
if [ ! -d $clonePath ]; then
INFO "Cloning $gitServer"
git clone $gitServer $clonePath || { ERROR "ERROR cloning $gitServer"; return 1;}
pushd $clonePath
INFO "Updating Submodules (gsui)"
git submodule update --init
INFO "adding user fork ${user_name}"
git remote add $user_name $gitServer.$user_name
git fetch $user_name
popd
INFO "Opening $clonePath in vscode"
fi
code $clonePath
}
last time when I tried to parse a url in bash I struggled with the whole split an item into an array. so I decided i'd try to use ruby (since it has a easy split method) so i've tried things like
$ gitServer='ssh://mycompany#vs-ssh.visualstudio.com:22/someProject/_ssh/myRepo'
$ ruby -e "a = '$gitServer'; b=a.split('/'); p b"
["ssh:", "", "mycompany#vs-ssh.visualstudio.com:22", "someProject", "_ssh", "myRepo"]
$ foo=`ruby -e "a = '$gitServer'; b=a.split('/'); p b"`
$ echo "${c[3]}"
$ echo "${c[0]}"
["ssh:", "", "mycompany#vs-ssh.visualstudio.com:22", "someProject", "_ssh", "myRepo"]
so I dunno. I don't have to use ruby it just seemed like a easy solution... now not so much. So how can I get the project and repository name out of the url in either bash or bash using ruby?
Here is a way you can get the values into environment variables using Ruby:
Assuming you have a URL environment variable containing the git repo url, such as created by the line below:
export URL='ssh://mycompany#vs-ssh.visualstudio.com:22/someProject/_ssh/myRepo'
You can do the following to put your desired values into other environment variables:
export PROJECT=`ruby -e "puts ENV['URL'].split('/')[3]"`
export REPO_NAME=`ruby -e "puts ENV['URL'].split('/')[5]"`
I'm working on a fairly large git repo with a couple of thousand (remote) branches. I am used to using auto-completion (using [TAB]) in the console (Git Bash in that case), so I unconsciously do that for git commands, too.
e.g. I'd type
git checkout task[TAB]
with the effect that the console stalls for often minutes. Is there a way to limit auto-completion to local branches only?
With Git 2.13 (Q2 2017), you can disable (some of) the branch completion.
git checkout --no-guess ...
# or:
export GIT_COMPLETION_CHECKOUT_NO_GUESS=1
See commit 60e71bb (21 Apr 2017) by Jeff King (peff).
(Merged by Junio C Hamano -- gitster -- in commit b439747, 01 May 2017)
As documented in contrib/completion/git-completion.bash now:
You can set the following environment variables to influence the behavior of the completion routines:
GIT_COMPLETION_CHECKOUT_NO_GUESS
When set to "1", do not include "DWIM" suggestions in git-checkout
completion (e.g., completing "foo" when "origin/foo" exists).
Note: DWIM is short for Do What I Mean, where a system attempts to anticipate what users intend to do, correcting trivial errors automatically rather than blindly executing users' explicit but potentially incorrect inputs.
completion: optionally disable checkout DWIM
When we complete branch names for "git checkout", we also complete remote branch names that could trigger the DWIM behavior. Depending on your workflow and project, this can be either convenient or annoying.
For instance, my clone of gitster.git contains 74 local "jk/*" branches, but origin contains another 147.
When I want to checkout a local branch but can't quite remember the name, tab completion shows me 251 entries. And worse, for a topic that has been picked up for pu, the upstream branch name is likely to be similar to mine, leading to a high probability that I pick the wrong one and accidentally create a new branch.
Note: "picked up for pu": see a What's cooking in git.git: it starts with:
Commits prefixed with '-' are only in 'pu' (proposed updates) while commits prefixed with '+' are in 'next'.
This is part of the Git Workflow Graduation process.
pu (proposed updates) is an integration branch for things that are not quite ready for inclusion yet
This patch adds a way for the user to tell the completion
code not to include DWIM suggestions for checkout.
This can already be done by typing:
git checkout --no-guess jk/<TAB>
but that's rather cumbersome.
The downside, of course, is that you no longer get completion support when you do want to invoke the DWIM behavior.
But depending on your workflow, that may not be a big loss (for instance, in git.git I am much more likely to want to detach, so I'd type "git checkout origin/jk/<TAB>" anyway).
I'm assuming that you are using the git-completion.bash script, and that you only care about git checkout.
To accomplish this, I just changed one line in the definition of the _git_checkout () function in git-completion.bash:
< __gitcomp_nl "$(__git_refs '' $track)"
---
> __gitcomp_nl "$(__git_heads '' $track)"
My understanding is that this only affects the tab-completion action (because of its location within the * case of the switch-case statement).
If you installed git-completion via homebrew, it's located here:
/usr/local/etc/bash_completion.d/git-completion.bash
Following erik.weathers' answer above, I made the following change so autocompletion can work for both local and remote based on the current prefix. By default, it'll only search local, but if I specify origin/… it'll know I want to search remote branches too.
In the _git_checkout () method, change
__gitcomp_nl "$(__git_refs '' $track)"
to:
# only search local branches instead of remote branches if origin isn't specified
if [[ $cur == "origin/"* ]]; then
__gitcomp_nl "$(__git_refs '' $track)"
else
__gitcomp_nl "$(__git_heads '' $track)"
fi
Of course, you can change origin to something else or you can have it search through through a list of remote prefixes if you have more than 1.
You can hack /etc/bash_completion.d/git
You'll need to edit __git_refs ()
Note that the change in behaviour will apply every where (so even with git push/pull where you might not want it to). You could of course, make a copy of the function or pass an extra parameter, but I leave that to you
You could think that you just the local branches with the alias co and all the branches with the complete command checkout.
You could perform the following. In your .bashrc, you redefine the _git_checkout() function. You let this function unchanged, except the end:
if [ $command -eq "co" ]; then
__gitcomp "$(__git_refs_local '' $track)"
else
__gitcomp "$(__git_refs '' $track)"
fi
Then, you just have to define a new function, __git_refs_local, where you remove the remote stuff.
Carey Metcalfe wrote a blog post containing a solution that also edits the auto-completion function, but with slightly newer code than other answers. He also defines an alias checkoutr that keeps the old auto-complete behavior in case it’s ever needed.
In short, first create the checkoutr alias with this command:
git config --global alias.checkoutr checkout
Then find git-completion.bash, copy the _git_checkout function into your shell’s RC file so that it gets redefined, and inside that function, replace this line:
__git_complete_refs $track_opt
with the following lines:
if [ "$command" = "checkoutr" ]; then
__git_complete_refs $track_opt
else
__gitcomp_direct "$(__git_heads "" "$cur" " ")"
fi
See the blog post for more details and potential updates to the code.
Modifying $(brew --prefix)/etc/bash_completion.d/git-completion.bash is not a good idea because it will be overwritten every time you update Git through Homebrew.
Combining all the answers I overwrite only _git_checkout function from the completion file in my .bash_profile after sourcing the completion file:
_git_checkout ()
{
__git_has_doubledash && return
case "$cur" in
--conflict=*)
__gitcomp "diff3 merge" "" "${cur##--conflict=}"
;;
--*)
__gitcomp "
--quiet --ours --theirs --track --no-track --merge
--conflict= --orphan --patch
"
;;
*)
# check if --track, --no-track, or --no-guess was specified
# if so, disable DWIM mode
local flags="--track --no-track --no-guess" track=1
if [ -n "$(__git_find_on_cmdline "$flags")" ]; then
track=''
fi
# only search local branches instead of remote branches if origin isn't
# specified
if [[ $cur == "origin/"* ]]; then
__gitcomp_nl "$(__git_refs '' $track)"
else
__gitcomp_nl "$(__git_heads '' $track)"
fi
;;
esac
}
I'm not using Git Bash myself, but if this is the same as mentioned in
http://tekrat.com/2008/04/30/bash-autocompletion-git-super-lazy-goodness/, you should be able to replace git branch -a with a plain git branch in
_complete_git() {
if [ -d .git ]; then
branches=`git branch -a | cut -c 3-`
tags=`git tag`
cur="${COMP_WORDS[COMP_CWORD]}"
COMPREPLY=( $(compgen -W "${branches} ${tags}" -- ${cur}) )
fi
}
complete -F _complete_git git checkout
(in your .profile or similar) and get what you want.
FWW here is a hack to __git_complete_refs that does the trick
__git_complete_refs ()
{
local remote track pfx cur_="$cur" sfx=" "
while test $# != 0; do
case "$1" in
--remote=*) remote="${1##--remote=}" ;;
--track) track="yes" ;;
--pfx=*) pfx="${1##--pfx=}" ;;
--cur=*) cur_="${1##--cur=}" ;;
--sfx=*) sfx="${1##--sfx=}" ;;
*) return 1 ;;
esac
shift
done
echo cur_ $cur_ > a
if [[ $GIT_COMPLETION_CHECKOUT_NO_GUESS != 1 || $cur_ == "origin"* ]]; then
__gitcomp_direct "$(__git_refs "$remote" "$track" "$pfx" "$cur_" "$sfx")"
else
__gitcomp_direct "$(__git_heads "" "$cur_")"
fi
}
I'm using TortoiseHg 0.5 (which includes Mercurial 1.0.2) on Vista64. My understanding from the Mercurial Book is that Mercurial should handle filenames in a case-insensitive manner on a case-insensitive filesystem (such as NTFS, which is what I'm on). However I find that my installation of Mercurial is in fact sensitive to case:
>hg status -A foo
C foo
>hg status -A FOO
? FOO
Could this be a bug in Mercurial, a bug in the TortoiseHg build of Mercurial, or is it something else? How can I achieve case-insensitive filename handling from Mercurial on Windows?
This issue has been resolved in Mercurial 1.1! From the release notes: "Improved correctness in the face of casefolding filesystems".
On Windows, Mercurial now ignores case in its command line arguments:
>hg status -A foo
C foo
>hg status -A FOO
C foo
And it also is aware that filename changes that only involve case are not new files:
>ren foo FOO
>hg status -A fOO
C foo
Thus there's no longer any risk of overlooking changes due to mistypes on the command line.
However, be aware that the contents of the .hgignore file remain case sensitive. This is an issue only if you're using glob syntax; with regexp syntax you can put (?i) at the beginning of patterns to make them insensitive.
I think you misread the hgbook. The intro to section 7.7 is just describing the three different types of case sensitivity that exist in OSs, not saying that mercurial will mirror those semantics.
Later in section 7.7.2 'Detecting case conflicts' it says:
When operating in the working
directory, Mercurial honours the
naming policy of the filesystem where
the working directory is located. If
the filesystem is case preserving, but
insensitive, Mercurial will treat
names that differ only in case as the
same.
When you do hg status -A FOO the process that's happening within mercurial is:
Check if a file exists on the file system matching the file argument, 'FOO', -- and at this point it's being case insensitive so it finds 'foo' and says "yup, I've got a file"
Check if there's an entry in the file manifest matching the file argument, 'FOO', and there isn't, so status shows a '?' saying it's a file on disk that hg isn't tracking
To better see mercurial not caring about case on NTFS try these steps:
hg init
echo line > Foo
hg add Foo
hg commit -m 'committed Foo'
move Foo not-foo
move not-foo FOO
hg status
and you should see hg saying that nothing has changed because the only thing that has changed is the case which hg is ignoring for you.
When I do the same thing on linux I instead see:
! Foo
? FOO