virtualenv activation: No command 'Script' found - virtualenv

Ubuntu 14.04
My virtualenv worked. But now I can't activate it.
I get this result:
michael#michael:~$ source venv/gmv_venv/bin/activate
No command 'Script' found, did you mean:
Command 'script' from package 'bsdutils' (main)
Script: command not found
]0: command not found
michael#michael:: command not found
]0: command not found
michael#michael:: command not found
]0: command not found
michael#michael:: command not found
]0: command not found
michael#michael:: command not found
]0: command not found
michael#michael:: command not found
[01: command not found
: command not found
[01: command not found
: command not found
[01: command not found
: command not found
[01: command not found
: command not found
: command not found
[01: command not found
: command not found
bash: venv/gmv_venv/bin/activate: line 13: syntax error near unexpected token `('
Could you help me understand what have I done wrongly and what to do to repair.

Finally solved!
It seems that the "./bin/activate" file has been overwritten.
You can replace your activate file with the following script.
Remember to replace the env name with your environment name in line number 49
i.e
VIRTUAL_ENV='/root/env/arshad' to -> '/root/env/your_env_name'
script -
# This file must be used with "source bin/activate" *from bash*
# you cannot run it directly
if [ "${BASH_SOURCE-}" = "$0" ]; then
echo "You must source this script: \$ source $0" >&2
exit 33
fi
deactivate () {
unset -f pydoc >/dev/null 2>&1
# reset old environment variables
# ! [ -z ${VAR+_} ] returns true if VAR is declared at all
if ! [ -z "${_OLD_VIRTUAL_PATH:+_}" ] ; then
PATH="$_OLD_VIRTUAL_PATH"
export PATH
unset _OLD_VIRTUAL_PATH
fi
if ! [ -z "${_OLD_VIRTUAL_PYTHONHOME+_}" ] ; then
PYTHONHOME="$_OLD_VIRTUAL_PYTHONHOME"
export PYTHONHOME
unset _OLD_VIRTUAL_PYTHONHOME
fi
# This should detect bash and zsh, which have a hash command that must
# be called to get it to forget past commands. Without forgetting
# past commands the $PATH changes we made may not be respected
if [ -n "${BASH-}" ] || [ -n "${ZSH_VERSION-}" ] ; then
hash -r 2>/dev/null
fi
if ! [ -z "${_OLD_VIRTUAL_PS1+_}" ] ; then
PS1="$_OLD_VIRTUAL_PS1"
export PS1
unset _OLD_VIRTUAL_PS1
fi
unset VIRTUAL_ENV
if [ ! "${1-}" = "nondestructive" ] ; then
# Self destruct!
unset -f deactivate
fi
}
# unset irrelevant variables
deactivate nondestructive
VIRTUAL_ENV='/root/env/arshad'
export VIRTUAL_ENV
_OLD_VIRTUAL_PATH="$PATH"
PATH="$VIRTUAL_ENV/bin:$PATH"
export PATH
# unset PYTHONHOME if set
if ! [ -z "${PYTHONHOME+_}" ] ; then
_OLD_VIRTUAL_PYTHONHOME="$PYTHONHOME"
unset PYTHONHOME
fi
if [ -z "${VIRTUAL_ENV_DISABLE_PROMPT-}" ] ; then
_OLD_VIRTUAL_PS1="${PS1-}"
if [ "x" != x ] ; then
PS1="${PS1-}"
else
PS1="(`basename \"$VIRTUAL_ENV\"`) ${PS1-}"
fi
export PS1
fi
# Make sure to unalias pydoc if it's already there
alias pydoc 2>/dev/null >/dev/null && unalias pydoc || true
pydoc () {
python -m pydoc "$#"
}
# This should detect bash and zsh, which have a hash command that must
# be called to get it to forget past commands. Without forgetting
# past commands the $PATH changes we made may not be respected
if [ -n "${BASH-}" ] || [ -n "${ZSH_VERSION-}" ] ; then
hash -r 2>/dev/null
fi
In case this doesn't work-
(It might be the case that the version of virtualenv I am using is different from yours.)
You can get the script that is compatible with your version by -
making a new dummy virtualenv and copying the contents of the dummy_env/bin/activate file to your_env/bin/actiavte and replace the env name with your_env.

Related

How can I edit crontabs in VS Code?

If I try to use Visual Studio Code (on macOS 10.15) to edit my crontab, it opens an empty file without the contents of my crontab.
$ VISUAL='code' crontab -e
crontab: no changes made to crontab
I didn't actually expect this to work (without -w) but include it for completeness. But when I add the -w it still fails.
$ VISUAL="code -w" crontab -e
crontab: code -w: No such file or directory
crontab: "code -w" exited with status 1
It occurred to me that there may be some weirdness with quoting, but neither single quotes nor the following fixed anything:
$ function codew() {
function> code -w "$1"
function> }
$ export VISUAL='codew'
$ crontab -e
The problem seems to be that the crontab's tempfile is not actually present. But how do I solve this? How can I use VS Code to edit crontabs?
Create a file touch ~/code-wait.sh:
#!/bin/bash
OPTS=""
if [[ "$1" == /tmp/* ]]; then
OPTS="-w"
fi
/usr/local/bin/code ${OPTS:-} -a "$#"
Make this file executable:
chmod 755 ~/code-wait.sh
Add to your .bashrc or .bash_profile or .zshrc:
export VISUAL=~/code-wait.sh
export EDITOR=~/code-wait.sh
Run command:
EDITOR='code' crontab -e
here the setting works for me.
.bashrc
## vscode
export VISUAL=/path/to/code-wait.sh
export EDITOR=/path/to/code-wait.sh
code-wait.sh
#!/bin/sh
code -w $*
That is quite a complex issue because there is no way to detect which tool calls the preferred editor. The TTY is the same and no environment variables can help.
Still, I was able to come up with a solution that enables the foreground mode (wait) for temporary files. IMHO, most if not all tools that use external editors and are waiting for them to save the file do use temporary files.
Full script is at https://github.com/ssbarnea/harem/blob/master/bin/edit but I will include here the main snippet:
#!/bin/bash
OPTS=""
if [[ "$1" == /tmp/* ]]; then
OPTS="-w"
fi
/usr/local/bin/code ${OPTS:-} -a "$#"

Can zsh `else` reserved keyword command be aliased and the lexem itself be repurposed as `fi` keyword command?

Following ZSH: Call in-built function from zsh function that uses the same name and Run a command that is shadowed by an alias, it might be expected that a command keyword equivalent of what builtin and command are doing for their respective eponymous token category; so that
if [ -z 'love' ]; then echo 'sad world'; keyword else echo 'wonderful world'; fi
would be equivalent to
if [ -z 'love' ]; then echo 'sad world'; else echo 'wonderful world'; fi
This problem was found in the following tricky scenario: being able to replace else with alie and fi with else. See Can zsh buildtins be aliased? for more details.
So an hypothetical attempt to implement that, if the keyword command existed, would be:
alias alie="keyword else"
alias else='fi'
So, to sum it up, the question is how do you make the following peace of zsh code works as expected by the previous command:
if [ -z 'love' ]; then echo 'sad world'; alie echo 'wonderful world'; else
This is not yet a working solution, but here is an idea: using the -r flag of enable and disable builtin commands to change visibility of the else keyword. So:
alias se='enable -r else; if'
alias alie='else'
disable -r else
alias else="fi; disable -r else"
This unfortunately doesn't work
se [ -z 'amo' ]; then echo 'trista mondo'; alie echo 'mirinda mondo'; else
# zsh: parse error near `fi'
This is however really on the "else" substitution that something break, as a non-inline version will indeed enter the else-branch and print "mirinda mondo".

How to automatically activate virtualenvs when cd'ing into a directory

I have a bunch of projects in my ~/Documents. I work almost exclusively in python, so these are basically all python projects. Each one, e.g. ~/Documents/foo has its own virtualenv, ~/Documents/foo/venv (they're always called venv). Whenever I switch between projects, which is ~10 times a day, I do
deactivate
cd ..
cd foo
source venv/bin/activate
I've reached the point where I'm sick of typing deactivate and source venv/bin/activate. I'm looking for a way to just cd ../foo and have the virtualenv operations handled for me.
I'm familiar with VirtualEnvWrapper which is a little heavy-handed in my opinion. It seems to move all your virtualenvs somewhere else, and adds a little more complexity than it removes, as far as I can tell. (Dissenting opinions welcome!)
I am not too familiar with shell scripting. If you can recommend a low-maintenance script to add to my ~/.zshrc that accomplishes this, that would be more than enough, but from some quick googling, I haven't found such a script.
I'm a zsh/oh-my-zsh user. oh-my-zsh doesn't seem to have a plugin for this. The best answer to this question would be someone contributing an oh-my-zsh plugin which does this. (Which I might do if the answers here are lackluster.
Add following in your .bashrc or .zshrc
function cd() {
builtin cd "$#"
if [[ -z "$VIRTUAL_ENV" ]] ; then
## If env folder is found then activate the vitualenv
if [[ -d ./.env ]] ; then
source ./.env/bin/activate
fi
else
## check the current folder belong to earlier VIRTUAL_ENV folder
# if yes then do nothing
# else deactivate
parentdir="$(dirname "$VIRTUAL_ENV")"
if [[ "$PWD"/ != "$parentdir"/* ]] ; then
deactivate
fi
fi
}
This code will not deactivate the virtualenv even if someone goes into subfolder. Inspired by answers of #agnul and #Gilles.
If the virtualenv is made by pipenv, then please consider this wiki page.
Furthermore, for added security please consider direnv.
Put something like this in your .zshrc
function cd() {
if [[ -d ./venv ]] ; then
deactivate
fi
builtin cd $1
if [[ -d ./venv ]] ; then
. ./venv/bin/activate
fi
}
Edit: As noted in comments cd-ing into a subfolder of the current virtual env would deactivate it. One idea could be to deactivate the current env only if cd-ing into a new one, like
function cd() {
builtin cd $1
if [[ -n "$VIRTUAL_ENV" && -d ./venv ]] ; then
deactivate
. ./venv/bin/activate
fi
}
that could still be improved, maybe turning it into a "prompt command" or attempting some prefix matching on the folder names to check there's a virtual env somewhere up the path, but my shell-fu is not good enough.
You should try something like autoenv if not direnv.
The first one is considered to be "lightweight", while the second one "simply, higher quality software", listening respectively to each one's author, talking about the other one's project. Thus, they seem to me fairly good options, to try both!
Anyway, both have been tested on zsh shells.
In particular, autoenv is really simple to use, after installing it:
$ git clone git://github.com/inishchith/autoenv.git ~/.autoenv
$ echo 'source ~/.autoenv/activate.sh' >> ~/.bashrc
just "follow the white rabbit " and try for example
$ mkdir project
$ echo "echo 'whoa'" > project/.env
$ cd project
whoa
"If a directory contains a .env file, it will automatically be executed when you cd into it. When enabled (set AUTOENV_ENABLE_LEAVE to a non-null string), if a directory contains a .env.leave file, it will automatically be executed when you leave it."
Have a look at https://github.com/inishchith/autoenv for more detailed instructions!...
Rather than writing a custom script you could use direnv. It's not a zsh specific solution (for that you could try zsh-autoenv), but is well-maintained and easy to use with zsh. Once you've installed it, you'd want to put eval "$(direnv hook zsh)" at the end of your .zshrc. At that point you can do:
$ source ~/.zshrc
$ cd foo
$ echo "layout python" > .envrc
direnv: error .envrc is blocked. Run `direnv allow` to approve its content.
$ direnv allow
direnv: loading .envrc
direnv: export +VIRTUAL_ENV ~PATH
Now you should be in your virtualenv. You can test by running pip freeze to see that your virtualenv specific packages are installed. To deactivate
$ cd ..
direnv: unloading
By far the easiest option (in 2019+) is to add virtualenvwrapper into your ~/.zshrc plugins
For example:
plugins=(
git pip python brew virtualenvwrapper
)
For anyone using (or considering to use) pyenv this can be achieved very conveniently using the pyenv-virtualenv plugin as described here.
Basically you simply add a .python-version file to the directory in which the name of the virtualenv is specified.
For posterity: I used #MS_'s solution but ran into the problem where cding directly from one project to another deactivates the old virtualenv but doesn't activate the new one. This is a slightly modified version of that solution which solves this problem:
# auto activate virtualenv
# Modified solution based on https://stackoverflow.com/questions/45216663/how-to-automatically-activate-virtualenvs-when-cding-into-a-directory/56309561#56309561
function cd() {
builtin cd "$#"
## Default path to virtualenv in your projects
DEFAULT_ENV_PATH="./env"
## If env folder is found then activate the vitualenv
function activate_venv() {
if [[ -f "${DEFAULT_ENV_PATH}/bin/activate" ]] ; then
source "${DEFAULT_ENV_PATH}/bin/activate"
echo "Activating ${VIRTUAL_ENV}"
fi
}
if [[ -z "$VIRTUAL_ENV" ]] ; then
activate_venv
else
## check the current folder belong to earlier VIRTUAL_ENV folder
# if yes then do nothing
# else deactivate then run a new env folder check
parentdir="$(dirname ${VIRTUAL_ENV})"
if [[ "$PWD"/ != "$parentdir"/* ]] ; then
echo "Deactivating ${VIRTUAL_ENV}"
deactivate
activate_venv
fi
fi
}
This is a zsh only solution.
This is an improvement over daveruinseverything's answer which is an improvement over MS_'s answer.
We are using precmd hook instead of overwriting cd.
We have added another extra feature. Suppose the directory structure is
├── .venv
│ ├── bin
│ │ └── activate
├── subdir
│ ├── subdir1
│ │ ├── subdir2
│ │ │ └── test2.txt
│ │ └── test1.txt
│ └── test.txt
└── testing.py
If you now open new terminal in subdir2, or directly cd to subdir2 from other place, it will activate the venv.
The solution is:
autoload -Uz add-zsh-hook
add-zsh-hook precmd automatically_activate_python_venv
function automatically_activate_python_env() {
if [[ -z $VIRTUAL_ENV ]] ; then
activate_venv
else
parentdir="$(dirname ${VIRTUAL_ENV})"
if [[ "$PWD"/ != "$parentdir"/* ]] ; then
deactivate
activate_venv
fi
fi
}
function activate_venv() {
local d n
d=$PWD
until false
do
if [[ -f $d/.venv/bin/activate ]] ; then
source $d/.venv/bin/activate
break
fi
d=${d%/*}
# d="$(dirname "$d")"
[[ $d = *\/* ]] || break
done
}
that is the solution without cd'ing, with zsh set to setop auto_cd w'll be able to change directories without cd, just type directory name and hit enter.
it is anhence of above solution:
# auto activate virtualenv
# Modified solution based on https://stackoverflow.com/questions/45216663/how-to-automatically-activate-virtualenvs-when-cding-into-a-directory/56309561#56309561
function auto_active_env() {
## Default path to virtualenv in your projects
DEFAULT_ENV_PATH="./env"
## If env folder is found then activate the vitualenv
function activate_venv() {
if [[ -f "${DEFAULT_ENV_PATH}/bin/activate" ]] ; then
source "${DEFAULT_ENV_PATH}/bin/activate"
echo "Activating ${VIRTUAL_ENV}"
fi
}
if [[ -z "$VIRTUAL_ENV" ]] ; then
activate_venv
else
## check the current folder belong to earlier VIRTUAL_ENV folder
# if yes then do nothing
# else deactivate then run a new env folder check
parentdir="$(dirname ${VIRTUAL_ENV})"
if [[ "$PWD"/ != "$parentdir"/* ]] ; then
echo "Deactivating ${VIRTUAL_ENV}"
deactivate
activate_venv
fi
fi
}
chpwd_functions=(${chpwd_functions[#]} "auto_active_env")
Similar to Jake's answer but supports cding from one virtualenv to another. In this case it deactivates the old virtualenv then activates the new one.
function cd() {
builtin cd "$#"
if [[ ! -z "$VIRTUAL_ENV" ]] ; then
# If the current directory is not contained
# within the venv parent directory -> deactivate the venv.
cur_dir=$(pwd -P)
venv_dir="$(dirname "$VIRTUAL_ENV")"
if [[ "$cur_dir"/ != "$venv_dir"/* ]] ; then
deactivate
fi
fi
if [[ -z "$VIRTUAL_ENV" ]] ; then
# If config file is found -> activate the vitual environment
venv_cfg_filepath=$(find . -maxdepth 2 -type f -name 'pyvenv.cfg' 2> /dev/null)
if [[ -z "$venv_cfg_filepath" ]]; then
return # no config file found
fi
venv_filepath=$(cut -d '/' -f -2 <<< ${venv_cfg_filepath})
if [[ -d "$venv_filepath" ]] ; then
source "${venv_filepath}"/bin/activate
fi
fi
}
Here is (yet) another solution to automatically activate a virtual environment; it's based on a number of the answers already posted here.
This will work for any Virtual Environment name or directory (not just ./env, ./venv, etc.). Also supports subdirectories, as well as cd-ing into symlinks of virtual environment (parent) folders.
This code searches for a pyvenv.cfg file instead of a particular named directory. If one is found within a subdirectory of the current folder, the environment is automatically activated. Once inside a virtual environment, that state is retained until you move out of the parent virtual environment directory, at which point the environment is deactivated.
Place this inside your .bashrc or .bash_profile.
function cd() {
builtin cd "$#"
if [[ -z "$VIRTUAL_ENV" ]] ; then
# If config file is found -> activate the vitual environment
venv_cfg_filepath=$(find . -maxdepth 2 -type f -name 'pyvenv.cfg' 2> /dev/null)
if [[ -z "$venv_cfg_filepath" ]]; then
return # no config file found
fi
venv_filepath=$(cut -d '/' -f -2 <<< ${venv_cfg_filepath})
if [[ -d "$venv_filepath" ]] ; then
source "${venv_filepath}"/bin/activate
fi
else
# If the current directory is not contained
# within the venv parent directory -> deactivate the venv.
cur_dir=$(pwd -P)
venv_dir="$(dirname "$VIRTUAL_ENV")"
if [[ "$cur_dir"/ != "$venv_dir"/* ]] ; then
deactivate
fi
fi
}
Personally I think it's an improvement on a lot of the solutions here, since it should work for any virtual environment
This is my solution, which:
checks if already at the currently active venv, and do nothing in that case
if there is a venv folder, deactivate the active one if there is one
activate the new venv whatever if there was an old one or not.
In my bash_aliases:
function cd() {
builtin cd "$#"
if [ $(dirname "$VIRTUAL_ENV") == $(pwd) ] ; then
# Already at the active virtual env
return
fi
if [[ -d ./venv ]] ; then
if type deactivate > /dev/null 2>&1 ; then
printf "Deactivating virtualenv %s\n" "$VIRTUAL_ENV"
deactivate
fi
source ./venv/bin/activate
printf "Setting up virtualenv %s\n" "$VIRTUAL_ENV"
fi
}
This is my solution:
If VIRTUAL_ENV is not set then:
Check if we're inside a virtual env
If yes, then activate it
Else (VIRTUAL_ENV is defined), check that the current folder starts with $VIRTUAL_ENV (removing the /venv part) and verify that the deactivate command exists
Deactivate teh environment
This is the script:
function cd() {
builtin cd $1
if [[ -z "${VIRTUAL_ENV}" ]]; then
if [[ -d ./venv && -f ./venv/bin/activate ]]; then
source ./venv/bin/activate
fi
elif [[ ! "$(pwd)" == ${VIRTUAL_ENV:0:n-5}* && ! -z "$(command -v deactivate)" ]]; then
deactivate
fi
}
Note: You need to add this to .bashrc. If it doesn't work, check if your .profile is not overriding your command (it happened to me)
Based on #MS_'s solution:
function cd() {
builtin cd "$#"
## If env folder is found then activate the vitualenv
if [[ -d ./venv ]] ; then
source ./venv/bin/activate
fi
if [[ -n "$VIRTUAL_ENV" ]] ; then
## check the current folder belong to earlier VIRTUAL_ENV folder
# if yes then do nothing
# else deactivate
parentdir="$(dirname "$VIRTUAL_ENV")"
if [[ "$PWD"/ != "$parentdir"/* ]] ; then
deactivate
fi
fi
}
I've used direnv in the past, as others have mentioned. Lyft use aactivator for this exact scenario.
Once the venv is built it must be activated (added to $PATH). We use aactivator to automatically activate the venv each time a user enters the service directory and deactivates as they leave.
I tried direnv as suggested by others but found it a bit too opinionated and it didn't exactly do what I wanted.
The solution below is for fish shell users only. Also, it assumes a pyproject.toml file and stdlib's venv, but that can be easily changed.
The fish shell has the concept of event handlers so you can easily define a function that gets run whenever an "event" gets triggered (Unix signals, environment variables changing, etc). See this a blog post for a quick introduction.
Add the following to your ~/.config/fish/config.fish (and modify as needed):
function venv_activate --on-variable PWD
if test ! -e pyproject.toml
if test -n "$VIRTUAL_ENV"
deactivate
end
return
end
# echo "Found pyproject.toml"
if test ! -d .venv
# echo "Creating $(python -V) venv"
python -m venv .venv --prompt (basename (pwd))
end
source .venv/bin/activate.fish
end
As a side note, the above works nicely with pyenv's .python-version files as well.
You don't have to execute deactivate on the directory where venv exists. When virtual environment is active you can deactivate anywhere.
So, say you have 2 venvs, <somepath>/project1/venv and <somepath>/project2/venv, and currently project1/venv is active.
If you want to switch project2/venv, do below.
cd project2
deactivate && source ./venv/bin/activate
It will deactivate previous one and activate current one.
Now the above you can just make an alias, or shell function in ~/.zshrc as below:
function avenv(){
deactivate
source ./venv/bin/activate
}
go the path where you want to activate the venv and just run avenv.
Python venv has a feature called --prompt, while creating venv you can mention the prompt, so that in the terminal you will understand which venv is active.
python3 -m venv venv --prompt PROJECT1_VENV
Now in terminal, it will come as (PROJECT1_VENV) -> ~
You can use a zsh hook function that runs whenever you change directories. For example, you could add this to your ~/.zshrc:
# Define a function to activate/deactivate virtualenvs based on the current directory
function venv_cd() {
# Check if the current directory has a venv subdirectory
if [[ -d venv ]]; then
# If yes, activate it if it's not already active
if [[ "$VIRTUAL_ENV" != "$PWD/venv" ]]; then
source venv/bin/activate
fi
else
# If no, deactivate the current virtualenv if any
if [[ -n "$VIRTUAL_ENV" ]]; then
deactivate
fi
fi
}
Add the function to the chpwd hook, which runs after every cd
add-zsh-hook chpwd venv_cd
Optionally, run the function once at the start of the session
venv_cd
This should automatically activate the virtualenv in the current directory if it exists, or deactivate it if you move to a directory without one.
Here is an alternative which sets an env variable when cd'ing into a virtualenv directory and checks if an active subdir is a child-directory of said virtualenv.
This will also deactivate when exiting or cd'ing to another directory.
This assumes you're using Pyenv to manage your Python installations, however you can change the pyvenv.cfg notation to anything else.
function cd() {
builtin cd "$#"
if [[ -f ./pyvenv.cfg ]] ; then
export VENV_CURRENT=$PWD
source ./bin/activate
else
if [[ $(env | fgrep VENV_CURRENT) ]]; then
if ! [[ $(pwd | fgrep $VENV_CURRENT) ]]; then
unset VENV_CURRENT
deactivate
fi
fi
fi
}

Get fish shell to work with gcloud command line tools?

Has anyone had any luck getting fish shell to work with google's gcloud command line tools? I'm not an expert in Fish script but these are the two files gcloud needs to run (which work fine use Fish's bash mode). Fish doesn't allow you to source bash files from what I understand so these would need to be converted to Fish script?
path.bash
script_link="$( readlink "$BASH_SOURCE" )" || script_link="$BASH_SOURCE"
apparent_sdk_dir="${script_link%/*}"
if [ "$apparent_sdk_dir" == "$script_link" ]; then
apparent_sdk_dir=.
fi
sdk_dir="$( command cd -P "$apparent_sdk_dir" && pwd -P )"
bin_path="$sdk_dir/bin"
export PATH=$bin_path:$PATH
path.completion
_python_argcomplete() {
local IFS=''
COMPREPLY=( $(IFS="$IFS" COMP_LINE="$COMP_LINE" COMP_POINT="$COMP_POINT" _ARGCOMPLETE_COMP_WORDBREAKS="$COMP_WORDBREAKS" _ARGCOMPLETE=1 "$1" 8>&1 9>&2 1>/dev/null 2>/dev/null) )
if [[ $? != 0 ]]; then
unset COMPREPLY
fi
}
complete -o default -F _python_argcomplete "gcloud"
_completer() {
command=$1
name=$2
eval '[[ "$'"${name}"'_COMMANDS" ]] || '"${name}"'_COMMANDS="$('"${command}"')"'
set -- $COMP_LINE
shift
while [[ $1 == -* ]]; do
shift
done
[[ $2 ]] && return
grep -q "${name}\s*$" <<< $COMP_LINE &&
eval 'COMPREPLY=($'"${name}"'_COMMANDS)' &&
return
[[ "$COMP_LINE" == *" " ]] && return
[[ $1 ]] &&
eval 'COMPREPLY=($(echo "$'"${name}"'_COMMANDS" | grep ^'"$1"'))'
}
unset bq_COMMANDS
_bq_completer() {
_completer "CLOUDSDK_COMPONENT_MANAGER_DISABLE_UPDATE_CHECK=1 bq help | grep '^[^ ][^ ]* ' | sed 's/ .*//'" bq
}
unset gsutil_COMMANDS
_gsutil_completer() {
_completer "CLOUDSDK_COMPONENT_MANAGER_DISABLE_UPDATE_CHECK=1 gsutil help | sed /Additional/q | grep '^ ' | sed -e 's/^ //' -e 's/ .*//'" gsutil
}
unset gcutil_COMMANDS
_gcutil_completer() {
_completer "CLOUDSDK_COMPONENT_MANAGER_DISABLE_UPDATE_CHECK=1 gcutil help | grep -v '^information' | grep '^[a-z]' | sed -e 's/ .*//' -e '/^$/d'" gcutil
}
complete -o default -F _bq_completer bq
complete -o default -F _gsutil_completer gsutil
complete -o default -F _gcutil_completer gcutil
What worked for me was just using bass. Check it out:
https://github.com/edc/bass
Just take the lines that gcloud adds to your bash_profile, and prepend bass to them in your .config/fish/config.fish file, as follows:
# The next line updates PATH for the Google Cloud SDK.
bass source '/Users/hunter/bin/google-cloud-sdk/path.bash.inc'
# The next line enables shell command completion for gcloud.
bass source '/Users/hunter/bin/google-cloud-sdk/completion.bash.inc'
As of today, I was able just to do
brew install --cask google-cloud-sdk
Added source /usr/local/Caskroom/google-cloud-sdk/latest/google-cloud-sdk/path.fish.inc to my ~/.config/fish/config.fish
Clone https://github.com/aliz-ai/google-cloud-sdk-fish-completion then run install.sh.
For path.bash, all it does is add the Cloud SDK bin directory to your PATH. We put some weird stuff in there because we wanted it to work from inside the Cloud SDK directory even when behind, eg, a symlink. For your own system, just do the fsh equivalent of "export PATH=$PATH:/path/to/google-cloud-sdk/bin".
For the tab completion, I don't know how fsh's tab completion works, so I've got nothing.
Fish support is now included out of the box with gcloud, however I ran into a pretty annoying issue. The code included in google-cloud-sdk/path.fish.inc (and #nafg's answer) leaves the directory changed, resulting in each new shell session starting in the google-cloud-sdk directory.
The modification I made was fairly simple, adding two extra lines to get the current working directory and restore it afterwards. This seems to have resolved the issue for me, so hopefully will help anyone else googling for "fish gcloud" problems.
set restore_dir (pwd -P)
set sdk_dir (builtin cd "$apparent_sdk_dir" > /dev/null; and pwd -P)
set bin_path "$sdk_dir/bin"
cd "$restore_dir"
I was able to set up completion by executing this:
# fisher v3
fisher add aliz-ai/google-cloud-sdk-fish-completion
# fisher v4
fisher install aliz-ai/google-cloud-sdk-fish-completion
Fisher can be found here: https://github.com/jorgebucaran/fisher
using fisher:
fisher install lgathy/google-cloud-sdk-fish-completion
and you are good to go
There's an interesting approach here: http://michelpm.com/blog/2013/07/26/switching-from-zsh-to-fish/
Basically it will run a bash script in bash, but it will diff how it changes the environment and apply that in fish.
However it won't work for completions and for your path.bash it's overkill. More like:
Change var=value to set var value
Change [ ... ] to test ...
Change $( ... ) to ( ... )
if doesn't need then and ends with end
Change || to ; or and && to ; and
Change export to set -x
So without testing here's what I would try:
set script_link ( readlink "$BASH_SOURCE" ); or set script_link $BASH_SOURCE
set apparent_sdk_dir ${script_link%/*}
if test "$apparent_sdk_dir" == "$script_link" ;
set apparent_sdk_dir .
end
set sdk_dir ( command cd -P "$apparent_sdk_dir"; and pwd -P )
set bin_path $sdk_dir/bin
set -x PATH $bin_path:$PATH

Is there a way to launch emacs merge without first opening emacs and using M-x and more?

I sometimes want to merge multiple pairs of files, suppose I want to merge fileA.old and fileA.new, as well as fileB.old and fileB.new..and so on.Currently I have to open emacs. Do M-x ediff-merge-files and enter name of first file, return key, name of second file, return key..and im in merge mode...is there a way to launch emacs with both file names as arguments and land in merge mode?
You can pass Lisp code to Emacs through the command line:
emacs --eval '(ediff-merge-files "path/to/file1" "path/to/file2")'
Of course this could be wrapped in a script to make it more convenient to call. For instance, in a bourne shell, you could do a simple version like this:
#!/bin/sh
# check correct invocation
if [ $# != 2 ]; then
echo "USAGE: $(basename "${0}") <file1> <file2>"
exit 1
fi
# check that file1 exists and is readable
if [ -f "${1}" ]; then
if [ ! -r "${1}" ]; then
echo "Cannot open '${1}', access denied."
exit 3
fi
else
echo "File not found: '${1}'"
exit 2
fi
# check that file2 exists and is readable
if [ -f "${2}" ]; then
if [ ! -r "${2}" ]; then
echo "Cannot open '${2}', access denied."
exit 5
fi
else
echo "File not found: '${2}'"
exit 4
fi
# invoke emacs
emacs --eval "(ediff-merge-files \"${1}\" \"${2}\")"
If you save this in a file ediff on your $PATH, you can then simply write:
ediff file1 file2
on the command line and Emacs will pop up with the two given files in ediff-mode.