I have multiple directories like this
~/project/foo/Debug
~/project/bar/Debug
... and so on
Folders project
and Debug
are constants.
I am in Debug Directory, foo
and bar
are the project names. When I am in the ~/project/bar/Debug
, is it possible to set a variable to string bar
, and when when I am in directory ~/project/xxxxx/Debug
set the that variable to xxxxx
?
As faho pointed out in his answer the recently added string
builtin can be used for this if efficiency is critical. However, in this case I would probably use the traditional solution for its clarity and simplicity:
set var (basename (dirname $PWD))
If you don't want to pay the cost of two, very cheap, external commands I would do this rather than use a regex:
set components (string split -- / $PWD)
set var $components[-2]
You can even do that in a single statement:
set var (string split -- / $PWD)[-2]
The current directory is available via the PWD
variable, so you can test that:
set -g string # define variable globally
if test $PWD = ~/project/foo/Debug
set string foo
else if test $PWD = ~/project/bar/Debug
set string bar
end
Of course, that will become unwieldy if there's more than three projects, or if the list changes over time, so you can use fish's builtin string
tool to perform matching and replacing on it.
set -g string
if string match -q '/projects/*/Debug'
set string (string replace -r '.*/projects/([^/]+)/Debug' '$1' -- $PWD)
end
I suspect what you really want is to display your project name in place of the working directory in your prompt. If that is so and you use git, you can use this
function prompt_pwd --description 'Print the current working directory, shortened to fit the prompt'
set -q argv[1]; and switch $argv[1]
case -h --help
__fish_print_help prompt_pwd
return 0
end
# This allows overriding fish_prompt_pwd_dir_length from the outside (global or universal) without leaking it
set -q fish_prompt_pwd_dir_length; or set -l fish_prompt_pwd_dir_length 1
set -l tmp
set -l gitdir
# Replace everything up to the vcs root with [rootname]
# under the assumption that that is the name of the "project".
# TODO: On my machine, it seems that the last two components are the safer bet, e.g.
# kwin/tiling
# exercism/cli (go)
# elves/elvish (go)
# new/exa-git (aur)
# dev/fish-shell
#
# Either that, or a more robust system of abbreviations,
# a non-hacky solution for which needs dictionaries.
if set gitdir (git rev-parse --show-toplevel ^/dev/null)
set tmp (string replace -- $gitdir '' $PWD)
# Underline the "project name"
# FIXME: The coloring here will leak, but I can't see a way to just undo underlining.
set gitdir \[(set_color -u)(string replace -r '.*/' '' -- $gitdir)(set_color normal; set_color $fish_color_cwd)\]
else
# Replace $HOME with "~"
# Only if we're not in a gitdir, otherwise $HOME/dev/$HOME would give weird results.
set realhome ~
# FIXME: This will give weird results if any special regex chars are in $HOME,
# but it should be a regex match because we only want it replaced at the beginning of the string.
set tmp (string replace -r '^'"$realhome"'($|/)' '~$1' $PWD)
end
# The test will return false if $fish_... is non-numerical,
# and the replace will not replace anything, so the PWD will be unshortened.
# This is okay.
if [ $fish_prompt_pwd_dir_length -eq 0 ]
echo -s $gitdir $tmp
else
# Shorten to at most $fish_prompt_pwd_dir_length characters per directory
# but only after the gitdir
echo "$gitdir"(string replace -ar '(\.?[^/]{'"$fish_prompt_pwd_dir_length"'})[^/]*/' '$1/' $tmp)
end
end
which could also be adapted to e.g. mercurial or similar, though in my experience mercurial is rather slow to start and hence not something you want to happen every prompt.
Save it in ~/.config/fish/functions/prompt_pwd.fish.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With