Setting Up Fish Shell Profile - terminal

I am trying to set up my fish shell profile via the ~/.config/fish/config.fish command. I did not have a config.fish file and had to create my own after the install.
The main reason I want to update this profile is to show my current GitHub location in the terminal. I found the following settings online:
set -g -x fish_greeting ''
# fish git prompt
set __fish_git_prompt_showdirtystate 'yes'
set __fish_git_prompt_showstashstate 'yes'
set __fish_git_prompt_showupstream 'yes'
set __fish_git_prompt_color_branch yellow
# Status Chars
set __fish_git_prompt_char_dirtystate ' '
set __fish_git_prompt_char_stagedstate '→'
set __fish_git_prompt_char_stashstate '↩'
set __fish_git_prompt_char_upstream_ahead '↑'
set __fish_git_prompt_char_upstream_behind '↓'
function fish_prompt
printf ' '
set last_status $status
set_color $fish_color_cwd
printf '%s' (prompt_pwd)
set_color normal
printf '%s ' (__fish_git_prompt)
set_color normal
end
alias ls='ls -GFh'
alias fishprofile='nano ~/.config/fish/config.fish'
alias reboot='source ~/.config/fish/config.fish'
alias home='cd $HOME/Desktop'
function nvm
bass source ~/.nvm/nvm.sh ';' nvm $argv
end
cd ~/Desktop
After the code is pasted into the file path I am able to access the current GitHub terminal location, but as soon as the terminal has been relaunched this feature is gone. Any ideas on how to save this setting?

If you use the Fish way of doing things, there is no need for a config.fish file. What you show above is for compatibility reasons, and attempts to appease the config-file people. Fish's way of doing things is to define functions (instead of aliases) inside of individual files located (usually) at ~/.config/fish/functions/ . Variables are set and exported on the command-line, and are persistent.
See this page for more information about my points.

Related

What's the default root bash prompt?

In my case, the root bash prompt is
[hostname dir]# (in color red)
Where can I find the default bash prompt for the root user in my linux system?
I just found default plain user bash prompt in etc/skel/.bashrc
Edit based on OP's comment.
Looking at ArtixLinux bash source, PS1 is set as:
PS1='[\u#\h \W]\$ '
\u Username
\h Hostname (short)
\W Working Directory (basename)
\$ Prompt sign
If we look at the ss64 bash syntax-prompt page, we can find:
This change can be made permanent by placing the export PS1 definition in your ~/.bashrc file.
To see what is currently defined in your .bashrc/.bash_profile use grep 'PS1' $HOME/.bash{rc,_profile}
The default value on many distros is '\s-\v\$ '
So the default PROMT is:
\s: The name of the shell, the basename of $0 (the portion following the final slash).
-: Literal - char
\v: The version of Bash (e.g., 2.00)
\$: If you are not root, inserts a $; if you are root, you get a # (root uid = 0)
: Literal space
First, there is a configuration option to enable interpretation of backslash escapes in the PS1 string, --enable-prompt-string-decoding, and it's very commonly enabled.
Then, many distros come with a pre-set value of something like this, for example in Ubuntu:
if [ "$color_prompt" = yes ]; then
PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u#\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
else
PS1='${debian_chroot:+($debian_chroot)}\u#\h:\w\$ '
fi
If PS1 isn't set, the manual tells us
The default value is \s-\v\$ .
which looks something like -bash-5.1$ .
We can also see that in config-top.h in the source:
#define PPROMPT "\\s-\\v\\$ "
Once user logins into the system, user environment variables are initialized from various files:
/etc/profile or /etc/bashrc (system wide)
~/.bash_profile , ~/.bash_login , ~/.profile , ~/.bashrc or ~/.bash_logout (user)
gnu docs tell more about prompt
You can customise/define your prompt temporary means for current shell session
export PS1="\[\e]0;\u#\h: \w\a\]${debian_chroot:+($debian_chroot)}\u#\h:\w\$"
to make it permanent paste this line in .bashrc, and then source .bashrc
for more customisation

List files in directory as menu options and then run that selected script

First post here, and quite a newbie to using terminal. Sorry in advance for any fails.
I'm trying to list whatever .sh files are in a directory, so when i choose the file, it runs the file. The files are just .sh files that export environment variables so i can load a specific job im working on.
The thing is, if i copy the script and paste into terminal and run, it works.
But if i try to run the script through terminal. It works, but doesnt set the environment variables. Here's the script.
cd ~/nuke/pipeline/executables/
echo "-- JOB LIST --"
# set the prompt used by select, replacing "#?"
PS3="Use number to select a file or 'stop' to cancel: "
# allow the user to choose a file
select filename in *.sh
do
# leave the loop if the user says 'stop'
if [[ "$REPLY" == stop ]]; then break; fi
# complain if no file was selected, and loop to ask again
if [[ "$filename" == "" ]]
then
echo "'$REPLY' is not a valid number"
continue
fi
# now we can use the selected file, trying to get it to run the shell script
. $filename
echo "Job Environment is $filename"
# it'll ask for another unless we leave the loop
break
done
#And here's whats in one of the .sh files
export DIR=/Users/darren/nuke/pipeline
export JOB=RnD
export SHOT=base
The issue here is the sub shell. As you may be aware, environment variables set in a sub shell don't propagate to the parent.
Let's call the script in your question as menu.sh. It is calling other scripts based on user's choice, through this line:
. $filename
Looks like you are invoking your script as menu.sh. That would run in a sub shell and the environment variables set through the above . $filename call are lost when it finishes.
To make it work properly, you need to invoke menu.sh as:
source /path/to/menu.sh
or
. /path/to/menu.sh

Is it possible to specify the bash prompt using a command-line option?

I use vim a lot and often find it useful to drop into the command line using !bash.
However, I need to type exit to return to vim and sometimes I'm not sure whether I'm in a subshell or whether that will close my session.
What I'd really like to do is type something like !bash -prompt "subshell" so that I get something like this:
subshell$ <commands go here>
Is this possible?
The most direct way to do this is to set the PS1 environment variable within vim:
:let $PS1="subshell$ "
And start your sub-shells using the command :shell instead of :!bash.
Using the $ sign with let modifies an environment variable. Add this to your .vimrc to persist the setting.
Alternately, using :shell you can specify a more specific command, including arguments, using the shell option, see help shell and help 'shell'.
So:
:set shell=bash\ --rcfile\ ~/.vimbashrc
In .vimbashrc add PS1="subshell ", and invoke the sub-shells using :shell instead of !bash. Add this to your .vimrc to persist the setting.
So you have two options:
Add let $PS1="subshell " to your .vimrc, and start sub-shells using :shell instead of :!bash.
Make a custom rc file for your vim sub-shells, add your specific PS1="subshell " to it, and modify the shell option in your .vimrc: set shell=bash\ --rcfile\ ~/.vimbashrc.
Finally, if you must use :!bash to start the sub-shells there are a couple of more options. Note that you can also pass a more specific command line using !, e.g.:
:PS1="subshell$ " bash should work.
:!bash\ --rcfile\ ~/.vimbashrc, and set PS1 in .vimbashrc as above
But you'll need to type these every time, or define a mapping for it.
Use shell variable $SHLVL seems to be another option here. Add $SHLVL in your $PS1:
export PS1="$PS1 $SHLVL"
so your prompt looks like this:
[tim#RackAblade47 ~]$ 2
when you start shell from VIM, $SHLVL will increase:
[tim#RackAblade47 ~]$ 4
Yes - you can change the prompt inside the shell before running your commands
PS1="subshell"
checkout this guide for all the options http://www.linuxselfhelp.com/howtos/Bash-Prompt/Bash-Prompt-HOWTO-2.html
If you really must do it via the bash command you can use '--rcfile' to specify an RC file that runs the PS1 command for you (you usually put the PS1= line your .bashrc to customize the prompt at login)
To answer your original question, you can say inside Vim:
:!VIMPROMPT="(vim) " bash
and change your prompt (in your .bashrc, presumably) from something like
PS1='\u#\h:\w\$ '
to
PS1='$VIMPROMPT\u#\h:\w\$ '
this will change your prompt from
me#host:~$
to
(vim) me#host:~$
if run inside Vim.
I'm personally using
case $(ps $PPID) in *vim|*bash)
PS1="$(ps $PPID | awk '{print $NF}' | sed 1d) $PS1" ;;
esac
in my prompt script that's sourced by my .bashrc, taken from triplee's comment.
I have been able to change the prompt for a vim subshell process by checking for the MYVIMRC variable which is exported inside vim, and will then update PS1 accordingly. I updated my .bashrc file with the following.
PS1='\$ '
# when in vim subshell change PS1 for clarity
if [[ $MYVIMRC ]]; then PS1='>> '; fi;
Put this in your .bashrc after any existing PS1= statements.
if ps | grep -q vim; then
export PS1="[VIM]$PS1"
fi
Tested on Ubuntu.
You can send it to the background with CTRL+Z and then bring it back with the fg command. With jobs you see all the jobs you have stopped.
This was you can have multiple instances of vim in parallel and chose which one you want to bring back. If there's no running you will just get a no current job error and that's it.
This doesn't specifically answer your question, but addresses the problem underneath it.

Set screen-title from shellscript

Is it possible to set the Screen Title using a shell script?
I thought about something like sending the key commands ctrl+A shift-A Name enter
I searched for about an hour on how to emulate keystrokes in an shell script, but didn't find the answer.
You can set the screen / xterm title using the following lines:
#!/bin/bash
mytitle="Some title"
echo -e '\033k'$mytitle'\033\\'
[UPDATE] - by request I'm also including the solution proposed by #Espo below:
Depending on your xterm version or your linux distribution the line above may or may not work and you can try the xterm-defaults:
#!/bin/bash
mytitle="Some title"
echo -e '\033]2;'$mytitle'\007'
For more on the details see: http://www.faqs.org/docs/Linux-mini/Xterm-Title.html#s3 or refer to the answer by #Espo below.
From http://www.faqs.org/docs/Linux-mini/Xterm-Title.html#s3
xterm escape sequences
Window and icon titles may be changed
in a running xterm by using XTerm
escape sequences. The following
sequences are useful in this respect:
ESC]0;stringBEL -- Set icon name and window title to string
ESC]1;stringBEL -- Set icon name to string
ESC]2;stringBEL -- Set window title to string
where ESC is the escape character
(\033), and BEL is the bell character
(\007).
Printing one of these sequences within
the xterm will cause the window or
icon title to be changed.
Note: these sequences apply to most
xterm derivatives, such as nxterm,
color-xterm and rxvt. Other terminal
types often use different escapes; see
the appendix for examples. For the
full list of xterm escape sequences
see the file ctlseq2.txt, which comes
with the xterm distribution, or
xterm.seq, which comes with the rxvt
distribution.
Printing the escape sequences
For information that is constant
throughout the lifetime of this shell,
such as host and username, it will
suffice to simply echo the escape
string in the shell rc file:
echo -n "\033]0;${USER}#${HOST}\007"
should produce a title like
username#hostname, assuming the shell
variables $USER and $HOST are set
correctly. The required options for
echo may vary by shell (see examples
below).
For information that may change during
the shell's lifetime, such as current
working directory, these escapes
really need to be applied every time
the prompt changes. This way the
string is updated with every command
you issue and can keep track of
information such as current working
directory, username, hostname, etc.
Some shells provide special functions
for this purpose, some don't and we
have to insert the title sequences
directly into the prompt string. This
is illustrated in the next section.
The following are other ways to script the renaming of screen titles:
Adding the following settings to .ssh/config sets the screen title automatically upon logging in to a system using SSH:
Host *
PermitLocalCommand yes
LocalCommand [ "$TERM" == 'screen' ] && echo -ne "\033k%h\033\\"
Instead of %h, which represents the hostname of the machine you are connecting with, you may use %n, which is the actual name / alias you used to connect to the machine.
NOTE: You need OpenSSH >= v5.1 to be able to use the Localhost %n and %h parameters. Check out 'man ssh_config' for more info on LocalCommand.
To automatically revert the title, back to that of the hostname of the localhost, after closing the SSH session, you can add an escape sequence to you prompt variable PS1 in .bashrc :
export PS1='you_favorite_PS1_here'
if [ "$TERM" == 'screen' ]; then
export PS1=${PS1}'\[\033k\h\033\\\]'
fi
These tricks are especially useful when using a .screenrc config that shows you in what screen 'tab' you are currently working. Add something like the following to .screenrc to get this working:
caption always "%{= kY}%-w%{= Yk}%n %t%{-}%+w%{ kG} %-= #%H - %LD %d %LM - %c"
Try the below commands, no need to edit any file or configuration like ~/.bashrc, Can be used at runtime.
Set static text as title: (My Title)
export PS1='\[\e]0;My Title\a\]${debian_chroot:+($debian_chroot)}\u#\h:\w\$ '
Set local/global variable as title: ($USER)
export PS1='\[\e]0;$USER\a\]${debian_chroot:+($debian_chroot)}\u#\h:\w\$ '
Set command output as title: (hostname)
export PS1='\[\e]0;`hostname`\a\]${debian_chroot:+($debian_chroot)}\u#\h:\w\$ '
Set to default (Revert back):
export PS1='\[\e]0;\u#\h: \w\a\]${debian_chroot:+($debian_chroot)}\u#\h:\w\$ '
set_screen_title ()
{
echo -ne "\ek$1\e\\"
}
You can also call screen and tell it to set a title:
screen -X title "new title"
If you're in a screen window, it will set that window's name. If you're not in screen, it will set the most recently opened window's name.
To add to Espo's answer, the xterm escape sequences can also be applied to the Bash PS1 variable
ESC]0;stringBEL -- Set icon name and window title to string
ESC]1;stringBEL -- Set icon name to string
ESC]2;stringBEL -- Set window title to string
Example
PS1='\e]0;string\a'
To enable automatic title updating when jumping around with ssh, add this to ~/.bashrc:
ssh() {
echo -n -e "\033k$1\033\\"
/usr/bin/ssh "$#"
echo -n -e "\033k`hostname -s`\033\\"
}
echo -n -e "\033k`hostname -s`\033\\"
See http://linuxepiphany.blogspot.com.ar/2010/05/good-screenrc-config-setup.html
# add the following in your ~/.bashrc or ~/.bash_profile
PROMPT_COMMAND='printf "\033]0;%s#%s:%s\007" "${USER}" "${HOSTNAME%%.*}" "${PWD/#$HOME/~}"'
or even better copy the whole concept for customizing your bash configs between a lot of hosts from here
My solution to this problem was to create a bash script and add it to my ~/.bashrc file:
set-title() {
ORIG==$PS1
TITLE="\e];$#\a"
PS1=${ORIG}${TITLE}
}
Now when I'm in any bash shell session, I type "set-title desired_title" and it changes to "desired title".
This works for multiple versions of Ubuntu, currently on Kinetic 16.04
I got this solution from here. I was looking for it again, couldn't find it and thought I'd post it here for anyone interested.
I got this solution from experimenting with others, like #flurin-arner I started the #weston-ganger set-title(). I also used #imgx64 PROMPT_DIRTRIM suggestion. I'm also using #itseranga git branch prompt, though this has nothing to do with the question it does show what you can do with the prompt.
First as shown by weston and above
TITLE="\[\e]2;$*\a\]"
can be used to manually set the Terminal Title, "$*" is commandline input, but not what we want.
2nd as stated I'm also adding git branch to my prompt, again not part of the question.
export PROMPT_DIRTRIM=3
parse_git_branch() {
git branch 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/ (\1)/'
}
export PS1="\u#\h \[\033[32m\]\w\[\033[33m\]\$(parse_git_branch)\[\033[00m\] $ "
3rd, by experiment I copied the TITLE code above, set the $* to a fixed string and tried this:
see: \[\e]2;'SomeTitleString'\a\]
export PS1="\u#\h \[\033[32m\]\w\[\033[33m\]\$(parse_git_branch)\[\033[00m\]\[\e]2;'SomeTitleString'\a\] $ "
This had the desired effect! Ultimately, I wanted the base path as my title.
PS1 Params shows that \W is the base path so my solution is this:
export PS1="\u#\h \[\033[32m\]\w\[\033[33m\]\$(parse_git_branch)\[\033[00m\]\[\e]2;\W\a\] $ "
without the git branch:
export PS1="\u#\h \[\033[32m\]\w\[\033[33m\]\[\033[00m\]\[\e]2;\W\a\] $ "
resulting in a prompt with git-branch:
user#host ~/.../StudyJava (master) $
resulting in a prompt without parse_git_branch:
user#host ~/.../StudyJava $
where pwd gives
/home/user/somedir1/otherdir2/StudyJava
and Terminal Title
StudyJava
NOTE: From #seff above I am essentially replacing the "My Title" with "\W"
export PS1='\[\e]0;My Title\a\]${debian_chroot:+($debian_chroot)}\u#\h:\w\$ '
I tried this on Ubuntu 18.10 and it only worked with PROMPT_COMMAND in ~/.bashrc.
And if you override PROMPT_COMMAND, the behavior of the title changes slightly. I decided to change only if necessary:
t() {
TITLE="$#"
PROMPT_COMMAND='echo -ne "\033]0;${TITLE}\007"'
}
enter image description here

Should I put complex functionality in the shell login script or separate programs?

I have quite a few simple functions that I had previously kept in my .profile but I decided to put them in Perl scripts and add aliases to the Perl scripts. I feel like this is a bad idea, but the functionality looks/is better in Perl than bash since it is fairly complex (involving floating point math etc.).
Are there any best practices for login scripts and/or functions that are being put in the PATH variable (concerning both security and system stability issues)? Do you distribute functionality outside of the login script for complex tasks, or do you have a monolithic login script?
I guess this can be distilled to just a question about the validity of login script refactoring, and if it's valid how it's usually done.
I personally have a scripts directory ~/.bin, add it to PATH in ~/.profile, and keep all my personal scripts in there. I have bashlib in there which is sourced by all my other scripts and by ~/.bashrc which contains all my convenience functions.
My ~/.profile contains only environment variables that I need defined (like PATH), and my ~/.bashrc contains shell initialization and a few functions/aliases that are too simplistic to put in the form of a script.
The links show you how I set up those files.
By the way, refer to http://mywiki.wooledge.org/DotFiles for a description of how exactly the shell initialization happens; and which types of things go in which files.
I have a complex structured profile - with a load of scripts being used. The main issue is boot-strapping the system across all the different environments where it is used - Solaris, Linux (misc h/w), HP-UX, AIX...
I use Korn shell - but the principles apply to bash (and it works fine with bash):
#!/bin/ksh
#
# #(#)$Id: profile,v 6.8 2007/09/24 18:20:26 jleffler Exp $
#
# Generic profile for Jonathan Leffler (JL)
#
# Copyright (C) JLSS 1989-93,1995-99,2002,2005,2007
#TABSTOP=4
# Set machine-specific environment
mc=`uname -n`
if [ -r $HOME/.$mc ]
then
. $HOME/.$mc
fi
unset mc
# Set basic environment
: ${INFORMIXDIR:=/usr/informix} ; export INFORMIXDIR
: ${REAL_HOME:=$HOME} ; export REAL_HOME
# Machine-configurable PATH setting
for mcsetpath in ${REAL_HOME}/bin/mcsetpath ${HOME}/bin/mcsetpath
do
if [ -r $mcsetpath ]
then
. $mcsetpath # Set PATH
break;
fi
done
unset mcsetpath
. libpath # Set LD_LIBRARY_PATH
. ttyset # Set STTY values
. kshrc # Set KSH environment
. cdpath # Set CDPATH
. exinit # Set EXINIT
. termset # Set TERM type
. ixenviron # Set INFORMIX environment
. ccenviron # Set ClearCase environment
. setprompt # Set prompt
. manpath # Set MANPATH
umask 022
# Set group-specific environment
group=`id | sed 's/.* gid=[0-9]*(\([^)]*\)).*/\1/'`
if [ -f "$REAL_HOME/.$group" ]
then
. $REAL_HOME/.$group
fi
# Set user-specific environment -- assume LOGNAME or USER set OK
# Beware Linux: by default, username = group name so things get done twice!
: ${LOGNAME:=${USER:-jleffler}}
export LOGNAME
if [ "$group" != "$LOGNAME" ] && [ -f "$REAL_HOME/.$LOGNAME" ]
then
. $REAL_HOME/.$LOGNAME
else
cd
case "$-" in
*c*) : OK;;
*) echo "User $LOGNAME logged in to `pwd` at `date`";;
esac
trap "clear; exit 0" 0
fi
unset group
It depends entirely on the scope you intent these functions to have, and how you want them to interact with the rest of the system. You could go as far as putting them in /usr/local/bin (making them available to everyone) or as putting them in a special start-up script that you only invoke (explicitly) when you want them.
There is no "right answer" until you determine how you want to scope them, and then the right answer is "put them in the place that gives you the scope you want."
I adopted a few rules about script location.
alias is for convenience one-liners
~/bin/ contains anything complex enough to accept arguments
Custom scripts I use a lot go into version control. I sync source to a bin on my PATH
I commit mostly to 1 package manager, and let it own its default path
The benefits
aliases execute quickly. My shell configs stay small & fast
shell quickly finds the more complex favorites
valuable scripts are not lost; no versioning issues
my package manager of choice just works
Rule 2 is thanks to #mike-gleason 's answer. Like #lunath, I keep custom scripts in ~/bin/

Resources