Setting up Sublime to use bash aliases & functions - bash

I'm using sublime and would like to set it up so that my custom build system can see and use aliases and bash functions which I've setup in my ~/.bashrc, which works from my terminal.
In my .bashrc file I have a build function:
function build() {
// various bash commands
}
In my ~/Library/Application Support/Sublime Text 3/Packages/User directory I have a project.sublime-build file:
{
"cmd": ["build"],
"working_dir": "~/Mozilla/git-master",
"shell" : "true"
}
which doesn't work. How can I get sublime to see and use the build function defined in my .bashrc file?

Sublime can not read your .bashrc, so in order to use custom functions you'll have to create a build file:
#!/bin/bash
#contents of build() go here...
Save the file in ~/bin and set it to be executable. Then, modify your project.sublime-build file like so:
{
"cmd": ["build"],
"path": "~/bin:$PATH",
"working_dir": "~/Mozilla/git-master",
"shell" : "true"
}
And you should be all set.

Related

WSL bash in Visual Studio Code running .bashrc but not .bash_profile

Until recently, when I've launched the integrated terminal in Visual Studio Code, bash runs both my .bashrc and my .bash_profile files. But now it's only running the .bashrc file. I need it to run both.
Some details: VSC 1.70.1 (latest), with the "Remote - SSH" extension, running under Windows 10 (updated) with WSL 2 installed. When I launch a Microsoft terminal, it runs both .bashrc and .bash_profile, but VSC's integrated terminal only runs the former. This probably means I have s.t. wrong in my VSC config, but the settings there seem to change frequently and it's hard to keep up. The relevant parts seem to be
"terminal.integrated.defaultProfile.windows": "WSL",
"terminal.integrated.profiles.windows": {
"bash":{
"path": "C:\\Windows\\System32\\bash.exe",
"args": ["-l"]
},
"WSL": {
"path": "C:\\WINDOWS\\System32\\wsl.exe",
"args": [ ],
"icon": "terminal-ubuntu"
}
},
but that doesn't work, nor do any of the variants I've tried on the two "args" parameters, nor changing the defaultProfile to "bash" instead of "WSL".
Before I give in and put all my startup settings in my .bashrc file and get rid of my .bash_profile file, what do I yet lack?
The historical presumption on UNIX is that .bash_profile runs once when you log in, then .bashrc runs in each new shell. Thus, things that are inherited by child processes (like environment variables) go in .bash_profile so they can only run once per login (often, as a parent process to xinit or otherwise GUI startup), whereas things that need to be separately configured for each new shell (like aliases, non-exported functions, prompt settings, etc) go in .bashrc.
If, however, you're in an environment where .bash_profile isn't run during session creation, you might want to invoke it during .bashrc operation (so it happens during setup of any new interactive shell). Consider adding the following to your .bash_profile:
# put this at the top of your .bash_profile
[[ $profile_already_sourced ]] && return
declare -x profile_already_sourced=1 # export so we only run once per process tree
# ...set up your environment variables here...
[[ -s ~/.bashrc ]] && source ~/.bashrc
...and the following to your .bashrc:
# put this at the top of your .bashrc
[[ $bashrc_already_sourced ]] && return
declare -- bashrc_already_sourced=1 # do not export this!
# ...do your non-exported shell-local configuration here...
[[ -s ~/.bash_profile ]] && source ~/.bash_profile
...that way you can have each file source the other when needed without causing an infinite loop.
I can't reproduce this after even after upgrading to 1.70.1, so I'd recommend trying out these things:
try
"path": "C:\\WINDOWS\\System32\\wsl.exe",
"args": ["-e", "bash", "-li"]
to make sure that a login shell is started
if this changed after upgrading, read Help -> Release Notes to find out what might be responsible, e.g. the Shell integration is now enabled by default, so you might try "terminal.integrated.shellIntegration.enabled": false
sync / backup your settings, re-install vanilla VSC, check if behaviour is still the same

How to use function on git-prompt on Git Bash for Windows?

I want to use the last exit code to customize my bash prompt. So following this question I should add $? inside a function:
PROMPT_COMMAND=__prompt_command
__prompt_command() {
local EXIT="$?"
...
I tried many times, but whenever I add a function on my C:\Program Files\Git\etc\profile.d\git-prompt.sh file, Git Bash can't run this file, and it doesn't use it.
Is there a way to use a function on git-prompt.sh on Git Bash for Windows, or another approach to use the last exit code to customize the bash prompt?
Follow these instructions to configure your git-bash prompt.
First, open git-bash, and cd to your ~ directory.
Using vim or nano, edit your ~/.bash_profile file to contain the following two lines:
test -f ~/.profile && . ~/.profile
test -f ~/.bashrc && . ~/.bashrc
Then create a ~/.bashrc file and add your custom prompt command function in this file:
PROMPT_COMMAND=__prompt_command
__prompt_command() {
local EXIT="$?"
# The rest of your code here
}
Make sure your changes saved correctly for both your ~/.bash_profile and ~/.bashrc files.
Open a new git-bash window. Assuming you have no bugs in your __prompt_command() function, your custom prompt should display properly.
If you quickly want to test your prompt, you can instead just run source ~/.bashrc in your current git-bash window rather than launching a second one.

VSCode Integrated Terminal Doesn't Load .bashrc or .bash_profile

I have the following files to handle shell configuration:
#~/.bash_profile
if [ -f ~/.bashrc ]; then
source ~/.bashrc
fi
and
#~/.bashrc
... configure shell
If I open VSCode from the command line using code, my .bashrc is loaded whenever I add a new instance of the integrated shell.
However if I open VSCode via its icon, only my .profile is loaded.
How can I ensure my .bashrc is loaded instead?
I've tried various settings for the terminal.integrated.shellArgs.osx setting without any luck.
Simply add shell arguments to the VsCode settings.json file.
Paths to the settings.json file are as follows:
Windows: C:\Users\<username>\AppData\Roaming\Code\User\settings.json`
Linux: $HOME/.config/Code/User/settings.json
Mac: $HOME/Library/Application\ Support/Code/User/settings.json
Add one of the following:
"terminal.integrated.shellArgs.windows": ["-l"],
"terminal.integrated.shellArgs.linux": ["-l"],
"terminal.integrated.shellArgs.osx": ["-l"],
This will launch your shell of choice with the login argument. This will thus execute any user profile that is setup.
VSCode has deprecated "terminal.integrated.shellArgs.osx" in favor of using profiles. This does the trick for bash in osx. Omit the first line if you don't want bash to be your default profile:
"terminal.integrated.defaultProfile.osx": "bash",
"terminal.integrated.profiles.osx": {
"bash": {
"path": "bash",
"args": ["-l"]
}
}
Another possible solution that just worked for me. The settings.json file (whcih you can access in File > Preferences > Settings > Features > terminal > Integrated > Automation Shell: Linux) had a parameter
"terminal.integrated.inheritEnv": false
set to false by default. Changing it to true fixed the problem in my case.
I had the same problem with the Intellij Idea terminal on a Mac, the solution is the same for both. In settings change the path to the integrated terminal to "/bin/bash". Hope that helps.
You could also try the following:
1 Create a file named /usr/local/bin/bash-login and add :
#!/bin/bash
bash -l
2 Run:
chmod +x /usr/local/bin/bash-login
to make it executable.
3 On your VSC user settings add
{ "terminal.integrated.shell.osx": "/usr/local/bin/bash-login" }
The solution was described at https://github.com/Microsoft/vscode/issues/7263.
Hope it helps
"terminal.integrated.shellArgs.osx": ["-l"] is deprecated.
I personally wanted to use .bash_profile, so I made a .bashrc with this:
if [ -f ~/.bashrc ]; then
source ~/.bash_profile
fi
And then I had to do a full computer restart (just restarting VS code didn't work).
Bash will load various DotFiles sequentially:
~/.bash_profile
~/.bash_login
~/.profile
If ~/.bash_profile been loaded, the second and third one will not be loaded.
If ~/.bash_profile is not loaded, bash will find second one. If ~/.bash_login been loaded, the third one will not be loaded.
If ~/.bash_profile and ~/.bash_login are both not loaded, Bash will try to load ~/.profile file.
A fresh Ubuntu installation will only contains ~/.profile file. So I think it will be better NOT to use the ~/.bash_profile to avoid issues happening. Just use the ~/.profile file. Then your VSCode won't need to config anything.
I was having this issue too. But in my case I was on windows with Visual Studio code opening a remote dev env inside my CentOS WSL.
So fixing the configuration of this use case was a bit different.
In the IDE open settings. Then at the top select "Remote [WSL: XXX]"
The scroll down to Integrated -> Profiles: Linux
And click edit in settings.json
Then I added the following to the file:
"terminal.integrated.defaultProfile.linux": "bash",
"terminal.integrated.profiles.linux": {
"bash": {
"path": "bash",
"args": ["-l"]
}
}
Save the settings file and the next terminal you open will respect your ~/.bash_profile.
NOTE: my ~/.bash_profile had the same lines that someone else recommended adding to load the bashrc file in it already.

virtualenv name not show in zsh prompt

Recently, I give a try on oh my zsh, everything looks good till I try virtualevn and virtualenvwrapper. When I activate a virtualenv (e.g test), on normal bash, I will see the virtualenv name like:
(test)abc#abc:
But when I switched to zsh, I cannot see virtualenv name. Even though, I alr add virtualenv and virtualenvwrapper in plugins of oh my zsh. I also checked the activate file of my virtualenv, it contains:
f [ -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
Is it because the comparision ["x" != x] return true?
Updated:
I tried to echo $PS1 in activate file, and got this:
(test) %{$fg[magenta]%}%n%{$reset_color%}%{$fg[cyan]%}#%{$reset_color%}%{$fg[yellow]%}%m%{$reset_color%}%{$fg[red]%}:%{$reset_color%}%{$fg[cyan]%}%0~%{$reset_color%}%{$fg[red]%}|%{$reset_color%}%{$fg[cyan]%}⇒%{$reset_color%}
It seems the $PS1 is correct, but when I echo $PS1 in the terminal, the (test) is gone. It seems the $PS1 is override by something else!
Do this in ~/.zshrc:
plugins=(virtualenv)
POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(status virtualenv)
Caveats:
1 -- add that plugin in addition to other plugins you have.
2 -- I'm using the POWERLEVEL9K theme. Maybe you theme
The best solution is to add the following to the end of your ~/.zshrc file:
export VIRTUAL_ENV_DISABLE_PROMPT=
This will override the value in virtualenv.plugin.zsh - no need to change that file.
My setting to display Python virtualenv name for the default (a.k.a. robbyrussell) theme is the following.
In the .zshrc file
virtualenv added in plugins
Add custom function:
function virtualenv_info {
[ $VIRTUAL_ENV ] && echo '('`basename $VIRTUAL_ENV`') '
}
Navigate to your theme
My theme is the default theme for zsh:
$ vim ~/.oh-my-zsh/themes/robbyrussell.zsh-theme
Add this command right after existing PROMPT commands:
PROMPT+='%{$fg[green]%}$(virtualenv_info)%{$reset_color%}%'
Finally
$ source ~/.zshrc
PS: You can add your name or a few space before or after the PROMPT+.
Hope that helps!
Found the problem, it's due to the theme. The theme I used in the above case is pygmalion, it won't allow u to change $PS1.
After changed to robbyrussell theme, I can change $PS1 in terminal, but still cannot see the virtualenv name. After a while debugging, I found that by default the virtualenv plugin of oh my zsh disable the prompt:
# disables prompt mangling in virtual_env/bin/activate
export VIRTUAL_ENV_DISABLE_PROMPT=1
So just comment out the line in virtualenv plugin, problem solved.
As per this guide here
First add virtualenv dependency under plugin in file .zshrc
If this doesn't work for you, then it means that the theme(one of oh-my-zsh theme) you have selected doesn't include virtualenv name in bash prompt so try second step.
Go to file ~/.oh-my-zsh/themes/YOUR_THEME_NAME.zsh-theme and add this in base prompt
%{$fg[green]%}$(virtualenv_prompt_info)%{$reset_color%}%
NOTE: virtualenv_prompt_info is the name of function which is declared in ~/.oh-my-zsh/plugins/virtualenv/virtualenv.plugin.zsh. If your plugin file have different function name then change it accordingly.
Or you can declare your own function in ~/.zshrc file as shown in this guide
If you are using conda to start your virtual environment the envorionment variable will be different. To figure out the name of the environment that holds your virtaulenv name type printenv and look through the output. For me it is CONDA_PROMPT_MODIFIER
after you know the name of the variable open .zshrc and add this function
function virtualenv_info {
[ $CONDA_PROMPT_MODIFIER ] && echo `basename $CONDA_PROMPT_MODIFIER`
}
and below that add this line
PROMPT="%{$fg[green]%}$(virtualenv_info)%{$reset_color%}%${PROMPT}"
close the editor and type source .zshrc
In the case you installed Anaconda using Homebrew:
brew tap homebrew/cask-versions
brew cask install anaconda
And you are using POWERLEVEL9K theme
git clone https://github.com/bhilburn/powerlevel9k.git ~/.oh-my-zsh/custom/themes/powerlevel9k
All you need to do is add this line to the end of .zshrc :
POWERLEVEL9K_RIGHT_PROMPT_ELEMENTS=(status root_indicator background_jobs history time anaconda)
There's no need for virtualenv plugin.
Edited:
In case you already had conda installed for bash and you get:
zsh: command not found: conda
Run this:
~/anaconda3/bin/conda init zsh
I made it work following this link: https://askubuntu.com/a/387098
I reproduce the answer below.
How the prompt is changed is defined in the script bin/activate inside the virtual environment directory. This file is created by virtualenv from a template. Unfortunatelly, the only way of prompt modification provided by the template is prepending (env name) or whatever is set with --prompt.
To modify the prompt in the way you want, I'd suggest circumventing the setting of the prompt in bin/activate and modify the definition of PROMPT in your theme file.
First add the following to your.zsh-theme (or .zshrc)
export VIRTUAL_ENV_DISABLE_PROMPT=yes
function virtenv_indicator {
if [[ -z $VIRTUAL_ENV ]] then
psvar[1]=''
else
psvar[1]=${VIRTUAL_ENV##*/}
fi
}
add-zsh-hook precmd virtenv_indicator
and add %(1V.(%1v).) in front of the second line of the definition of PROMPT. It should then look like this:
PROMPT='
%(1V.(%1v).)%{$fg_bold[grey]%}[%{$reset_color%}%{$fg_bold[${host_color}]%}%n#%m%{$reset_color%}%{$fg_bold[grey]%}]%{$reset_color%} %{$fg_bold[blue]%}%10c%{$reset_color%} $(git_prompt_info) $(git_remote_status)
%{$fg_bold[cyan]%}❯%{$reset_color%} '
If you want some color you could add %(1V.%{$fs_bold[yellow]%}(%1v)%{$reset_color%}.) for example.
Explanation:
virtenv_indicator will be called each time before the prompt is created. It checks if $VIRTUAL_ENV is set and not empty. If so, it sets the first element of the $psvar array to $VIRTUAL_ENV with everything before and including the last / removed (like basename $VIRTUAL_ENV but less expensive)
In the definition of PROMPT %(1V.(%1v).) checks if the first element of $psvar is set and not empty (%(1V.true-text.false-text)) and adds the content of the this element plus some parentheses ((%1v))
export VIRTUAL_ENV_DISABLE_PROMPT=yes disables any prompt setting by bin/activate scripts.
if you use zsh and pyenv, put this into ~/.zshrc
eval "$(pyenv init -)"
eval "$(pyenv virtualenv-init -)"
#export PS1='($(pyenv version-name)) '$PS1
export PYENV_VIRTUALENV_DISABLE_PROMPT=1
export BASE_PROMPT=$PS1
function updatePrompt {
if [[ "$(pyenv version-name)" != "system" ]]; then
# the next line should be double quote; single quote would not work for me
export PS1="($(pyenv version-name)) "$BASE_PROMPT
else
export PS1=$BASE_PROMPT
fi
}
export PROMPT_COMMAND='updatePrompt'
precmd() { eval '$PROMPT_COMMAND' } # this line is necessary for zsh
I am also using Oh My Zsh with the pygmalion theme. I had to edit the pygmalion script to add the virtual environment name before the prompt name.
open ~/.oh-my-zsh/themes/pygmalion.zsh-theme, modify the prompt_pygmalion_precmd function as following:
prompt_pygmalion_precmd(){
setopt localoptions extendedglob
local gitinfo=$(git_prompt_info)
local gitinfo_nocolor=${gitinfo//\%\{[^\}]##\}}
local exp_nocolor="$(print -P \"$base_prompt_nocolor$gitinfo_nocolor$post_prompt_nocolor\")"
local prompt_length=${#exp_nocolor}
local python_venv="($(echo $CONDA_DEFAULT_ENV)) "
PROMPT="${python_venv}${base_prompt}${gitinfo}${post_prompt}"
}
The following steps should solve the problem:
open ~/.p10k.zsh.
If you use only the left prompt, make the following changes:
typeset -g POWERLEVEL9K_LEFT_PROMPT_ELEMENTS=(
# =========================[ Line #1 ]=========================
os_icon # os identifier
dir # current directory
vcs # git status
# =========================[ Line #2 ]=========================
newline # \n
prompt_char # prompt symbol
virtualenv venv .venv env # show the venv on the second line
)
Add the following line, preferably after you adjust POWERLEVEL9K_VIRTUALENV_SHOW_WITH_PYENV:
typeset -g POWERLEVEL9K_VIRTUALENV_GENERIC_NAMES=()
Save the .p10k.zsh.
Restart the terminal.
Now, when you activate the virtual environment (on macOS source my_venv/bin/activate), then the name of the virtual environment (in my case, my_venv) and the version of Python installed on it (3.9.13) will appear after a beautiful Python symbol. Have a look at the attached screenshot.
I am using oh-my-zsh pygmalion them, and this works for me:
add virtualenv plugin in ~/.zshrc
open ~/.oh-my-zsh/themes/pygmalion.zsh-theme, modify the prompt_pygmalion_precmd function to this:
prompt_pygmalion_precmd(){
setopt localoptions extendedglob
local gitinfo=$(git_prompt_info)
local gitinfo_nocolor=${gitinfo//\%\{[^\}]##\}}
local exp_nocolor="$(print -P \"$base_prompt_nocolor$gitinfo_nocolor$post_prompt_nocolor\")"
local prompt_length=${#exp_nocolor}
local python_venv=$(virtualenv_prompt_info)
PROMPT="${python_venv}${base_prompt}${gitinfo}${post_prompt}"
}
Basically just add $(virtualenv_prompt_info) to your PROMPT to wherever you prefer, here I added it to the very beginning of my PROMPT.
You do not need to create new function, as per documentation - this function is created for you.
https://github.com/ohmyzsh/ohmyzsh/tree/master/plugins/virtualenv
But You still need to edit theme file, as mentioned above, just enter correct function name - virtualenv_prompt_info:
PROMPT+='%{$fg[green]%}$(virtualenv_prompt_info)%{$reset_color%}%'
After playing with the surround answers, I found the following to be the best for my use case. This checks the $VIRTUAL_ENV_PROMPT and $VIRTUAL_ENV variables every time you change directories and sets the prompt with the correct venv info.
DEFAULT_PROMPT=$PROMPT
function cd() {
builtin cd "$#"
if [[ -n "$VIRTUAL_ENV_PROMPT" ]] ; then
PROMPT="$VIRTUAL_ENV_PROMPT$DEFAULT_PROMPT"
elif [[ -n "$VIRTUAL_ENV" ]] ; then
PROMPT="(`basename $VIRTUAL_ENV`) $DEFAULT_PROMPT"
else
PROMPT=$DEFAULT_PROMPT
fi
}
export PS1='($(pyenv version-name)) '$PS1
source & link to issue #135 in pyenv-virtualenv repo:
https://github.com/pyenv/pyenv-virtualenv/issues/135#issuecomment-582180662
Back to 2023 : here something that worked for me with the theme .
Search the line for "plugins" and add virtualenv (if you are using this one)
plugins=(git python brew macos colored-man-pages virtualenv vscode)
Now look for the ZSH-Theme and use
ZSH_THEME="pygmalion-virtualenv"
Reload your terminal or kill your Visual Studio code window (reloading the terminal into VS cod didn't display the change for me...)

How to load .bash_aliases from perl/bash script

Lets say I have a perl script that setups a bash_aliases as follow
source file: bash_aliases.sh
alias w="cd /var/www"
install.pl
#!/usr/bin/perl
my $aliase_src= "${installation_dir}/bash_aliases.sh";
my $aliase_target="$ENV{'HOME'}/.bash_aliases";
if (! copy($aliase_src,$aliase_target))
{
print "Failed to copy file $aliase_src to Destination:$aliase_target. Reason:$! .";
die;
}
[command required to load .bash_aliases file]
I should be able to go as follow:
./install.pl
w
I dont want to :
./install.pl
source ~/.bash_aliases
w
I am unable to find command to load these aliases such that once the file is moved to home directory these aliases should be available to current script (install.pl) as well as all other script without running another command from command line e.g source ~/.bash_aliases OR . .bash_aliases
Edit
auto_load_aliases.sh using PROMPT_COMMAND (trying to following l0b0, answer)
#!/bin/bash
echo 'alias test="echo tested"' > $HOME/.bash_aliases
export PROMPT_COMMAND="$HOME/.bash_aliases";
this also did not work :
./auto_load_aliases.sh
test
What I expected what that auto_load_aliases.sh script sets the PROMPT_COMMAND , once it's set I have test aliase available.But that did not work.
~/.bash_aliases is not loaded by Bash by default, it is just a common convenience to avoid putting too much stuff in ~/.bashrc. If you want the aliases to be available in new Bash shells you have to source ~/.bash_aliases somewhere in ~/.bashrc. Some popular distributions (I believe Ubuntu is one) does this by default.
If you want to automatically source ~/.bash_aliases after changing it, you could try adding this in ~/.bashrc to source it after each command:
PROMPT_COMMAND='source ~/.bash_aliases'
If your alias file is very complex, you could make this faster by using inotifywait and only reloading the file when it changes.
Another way of loading aliases after changing them would be to replace the current shell with another one:
exec "$SHELL"
Bottom line, something has to change to automatically load new aliases. There is no built-in runtime configuration option in Bash to do this (and even then you'd have to enable that option).

Resources